^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Low-level ALSA driver for the ENSONIQ SoundScape
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) by Chris Rankin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This driver was written in part using information obtained from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * the OSS/Free SoundScape driver, written by Hannu Savolainen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/isa.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/firmware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/dma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/wss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/mpu401.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) MODULE_AUTHOR("Chris Rankin");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_DESCRIPTION("ENSONIQ SoundScape driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MODULE_FIRMWARE("sndscape.co0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_FIRMWARE("sndscape.co1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_FIRMWARE("sndscape.co2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MODULE_FIRMWARE("sndscape.co3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_FIRMWARE("sndscape.co4");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_FIRMWARE("scope.cod");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static bool joystick[SNDRV_CARDS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(id, "Description for SoundScape card");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) module_param_hw_array(port, long, ioport, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) module_param_hw_array(wss_port, long, ioport, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) module_param_hw_array(irq, int, irq, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) module_param_hw_array(dma, int, dma, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) module_param_hw_array(dma2, int, dma, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) module_param_array(joystick, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MODULE_PARM_DESC(joystick, "Enable gameport.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int isa_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int pnp_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct pnp_card_device_id sscape_pnpids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { .id = "ENS4081", .devs = { { "ENS1011" } } }, /* VIVO90 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { .id = "" } /* end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define HOST_CTRL_IO(i) ((i) + 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define HOST_DATA_IO(i) ((i) + 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define ODIE_ADDR_IO(i) ((i) + 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define ODIE_DATA_IO(i) ((i) + 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define CODEC_IO(i) ((i) + 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define IC_ODIE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define IC_OPUS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define RX_READY 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define TX_READY 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define CMD_ACK 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define CMD_SET_MIDI_VOL 0x84
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define CMD_GET_MIDI_VOL 0x85
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define CMD_XXX_MIDI_VOL 0x86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define CMD_SET_EXTMIDI 0x8a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define CMD_GET_EXTMIDI 0x8b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define CMD_SET_MT32 0x8c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define CMD_GET_MT32 0x8d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) enum GA_REG {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) GA_INTSTAT_REG = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) GA_INTENA_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) GA_DMAA_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) GA_DMAB_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) GA_INTCFG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) GA_DMACFG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) GA_CDCFG_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) GA_SMCFGA_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) GA_SMCFGB_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) GA_HMCTL_REG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define DMA_8BIT 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) enum card_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) MEDIA_FX, /* Sequoia S-1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) SSCAPE, /* Sequoia S-2000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) SSCAPE_PNP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) SSCAPE_VIVO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct soundscape {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int ic_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) enum card_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct resource *io_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct resource *wss_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct snd_wss *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned char midi_vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define INVALID_IRQ ((unsigned)-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static inline struct soundscape *get_card_soundscape(struct snd_card *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return (struct soundscape *) (c->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * Allocates some kernel memory that we can use for DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * I think this means that the memory has to map to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * contiguous pages of physical memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static struct snd_dma_buffer *get_dmabuf(struct soundscape *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct snd_dma_buffer *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) s->chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) size, buf) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) snd_printk(KERN_ERR "sscape: Failed to allocate "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "%lu bytes for DMA\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * Release the DMA-able kernel memory ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static void free_dmabuf(struct snd_dma_buffer *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (buf && buf->area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) snd_dma_free_pages(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * This function writes to the SoundScape's control registers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * but doesn't do any locking. It's up to the caller to do that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * This is why this function is "unsafe" ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) outb(reg, ODIE_ADDR_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) outb(val, ODIE_DATA_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * Write to the SoundScape's control registers, and do the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * necessary locking ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static void sscape_write(struct soundscape *s, enum GA_REG reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) sscape_write_unsafe(s->io_base, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Read from the SoundScape's control registers, but leave any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * locking to the caller. This is why the function is "unsafe" ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static inline unsigned char sscape_read_unsafe(unsigned io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) enum GA_REG reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) outb(reg, ODIE_ADDR_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return inb(ODIE_DATA_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * Puts the SoundScape into "host" mode, as compared to "MIDI" mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) static inline void set_host_mode_unsafe(unsigned io_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) outb(0x0, HOST_CTRL_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Puts the SoundScape into "MIDI" mode, as compared to "host" mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static inline void set_midi_mode_unsafe(unsigned io_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) outb(0x3, HOST_CTRL_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Read the SoundScape's host-mode control register, but leave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * any locking issues to the caller ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static inline int host_read_unsafe(unsigned io_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int data = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) data = inb(HOST_DATA_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Read the SoundScape's host-mode control register, performing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * a limited amount of busy-waiting if the register isn't ready.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Also leaves all locking-issues to the caller ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int host_read_ctrl_unsafe(unsigned io_base, unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) while (((data = host_read_unsafe(io_base)) < 0) && (timeout != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) --timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) } /* while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Write to the SoundScape's host-mode control registers, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * leave any locking issues to the caller ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static inline int host_write_unsafe(unsigned io_base, unsigned char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if ((inb(HOST_CTRL_IO(io_base)) & TX_READY) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) outb(data, HOST_DATA_IO(io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Write to the SoundScape's host-mode control registers, performing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * a limited amount of busy-waiting if the register isn't ready.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * Also leaves all locking-issues to the caller ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) while (!(err = host_write_unsafe(io_base, data)) && (timeout != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) --timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) } /* while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Check that the MIDI subsystem is operational. If it isn't,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * then we will hang the computer if we try to use it ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * NOTE: This check is based upon observation, not documentation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) static inline int verify_mpu401(const struct snd_mpu401 *mpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * This is apparently the standard way to initialise an MPU-401
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static inline void initialise_mpu401(const struct snd_mpu401 *mpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) outb(0, MPU401D(mpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * Tell the SoundScape to activate the AD1845 chip (I think).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * The AD1845 detection fails if we *don't* do this, so I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * think that this is a good idea ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void activate_ad1845_unsafe(unsigned io_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * Do the necessary ALSA-level cleanup to deallocate our driver ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void soundscape_free(struct snd_card *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) struct soundscape *sscape = get_card_soundscape(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) release_and_free_resource(sscape->io_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) release_and_free_resource(sscape->wss_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) free_dma(sscape->chip->dma1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * Tell the SoundScape to begin a DMA transfer using the given channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * All locking issues are left to the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sscape_write_unsafe(io_base, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) sscape_read_unsafe(io_base, reg) | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) sscape_write_unsafe(io_base, reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) sscape_read_unsafe(io_base, reg) & 0xfe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Wait for a DMA transfer to complete. This is a "limited busy-wait",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * and all locking issues are left to the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) udelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) --timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) } /* while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return sscape_read_unsafe(io_base, reg) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * Wait for the On-Board Processor to return its start-up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * acknowledgement sequence. This wait is too long for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * us to perform "busy-waiting", and so we must sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * This in turn means that we must not be holding any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * spinlocks when we call this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int obp_startup_ack(struct soundscape *s, unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) x = host_read_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (x == 0xfe || x == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) } while (time_before(jiffies, end_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * Wait for the host to return its start-up acknowledgement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * sequence. This wait is too long for us to perform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * "busy-waiting", and so we must sleep. This in turn means
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * that we must not be holding any spinlocks when we call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int host_startup_ack(struct soundscape *s, unsigned timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) unsigned long end_time = jiffies + msecs_to_jiffies(timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) x = host_read_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (x == 0xfe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) } while (time_before(jiffies, end_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * Upload a byte-stream into the SoundScape using DMA channel A.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int upload_dma_data(struct soundscape *s, const unsigned char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct snd_dma_buffer dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (!get_dmabuf(s, &dma, PAGE_ALIGN(32 * 1024)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * Reset the board ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * Enable the DMA channels and configure them ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) val = (s->chip->dma1 << 4) | DMA_8BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) sscape_write_unsafe(s->io_base, GA_DMAA_REG, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * Take the board out of reset ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * Upload the firmware to the SoundScape
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) * board through the DMA channel ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) while (size != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) unsigned long len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) len = min(size, dma.bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) memcpy(dma.area, data, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) data += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) size -= len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Don't forget to release this spinlock we're holding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) snd_printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) "sscape: DMA upload has timed out\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) } /* while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) set_host_mode_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) outb(0x0, s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * Boot the board ... (I think)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * If all has gone well, then the board should acknowledge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * the new upload and tell us that it has rebooted OK. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * give it 5 seconds (max) ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (!obp_startup_ack(s, 5000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) snd_printk(KERN_ERR "sscape: No response "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) "from on-board processor after upload\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) } else if (!host_startup_ack(s, 5000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) snd_printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) "sscape: SoundScape failed to initialise\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) _release_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * NOTE!!! We are NOT holding any spinlocks at this point !!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) free_dmabuf(&dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * Upload the bootblock(?) into the SoundScape. The only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * purpose of this block of code seems to be to tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * us which version of the microcode we should be using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int sscape_upload_bootblock(struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct soundscape *sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) const struct firmware *init_fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = request_firmware(&init_fw, "scope.cod", card->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) snd_printk(KERN_ERR "sscape: Error loading scope.cod");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) release_firmware(init_fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_lock_irqsave(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) data = host_read_ctrl_unsafe(sscape->io_base, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (data & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) spin_unlock_irqrestore(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) data &= 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (ret == 0 && data > 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) snd_printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) "sscape: timeout reading firmware version\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return (ret == 0) ? data : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * Upload the microcode into the SoundScape.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static int sscape_upload_microcode(struct snd_card *card, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct soundscape *sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) const struct firmware *init_fw = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) char name[14];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) snprintf(name, sizeof(name), "sndscape.co%d", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) err = request_firmware(&init_fw, name, card->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) err = upload_dma_data(sscape, init_fw->data, init_fw->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (err == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) snd_printk(KERN_INFO "sscape: MIDI firmware loaded %zu KBs\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) init_fw->size >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) release_firmware(init_fw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * Mixer control for the SoundScape's MIDI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static int sscape_midi_info(struct snd_kcontrol *ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) uinfo->value.integer.max = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static int sscape_midi_get(struct snd_kcontrol *kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct snd_ctl_elem_value *uctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) struct snd_wss *chip = snd_kcontrol_chip(kctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct snd_card *card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) register struct soundscape *s = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) uctl->value.integer.value[0] = s->midi_vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static int sscape_midi_put(struct snd_kcontrol *kctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct snd_ctl_elem_value *uctl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct snd_wss *chip = snd_kcontrol_chip(kctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) struct snd_card *card = chip->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct soundscape *s = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) unsigned char new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) new_val = uctl->value.integer.value[0] & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * We need to put the board into HOST mode before we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * can send any volume-changing HOST commands ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) set_host_mode_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * To successfully change the MIDI volume setting, you seem to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * have to write a volume command, write the new volume value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * and then perform another volume-related command. Perhaps the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * first command is an "open" and the second command is a "close"?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (s->midi_vol == new_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) goto __skip_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) change = host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) && host_write_ctrl_unsafe(s->io_base, new_val, 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) && host_write_ctrl_unsafe(s->io_base, new_val, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) s->midi_vol = new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) __skip_change:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * Take the board out of HOST mode and back into MIDI mode ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) set_midi_mode_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static const struct snd_kcontrol_new midi_mixer_ctl = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .name = "MIDI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .info = sscape_midi_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) .get = sscape_midi_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) .put = sscape_midi_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * The SoundScape can use two IRQs from a possible set of four.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * These IRQs are encoded as bit patterns so that they can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * written to the control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) static unsigned get_irq_config(int sscape_type, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) static const int valid_irq[] = { 9, 5, 7, 10 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static const int old_irq[] = { 9, 7, 5, 15 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) unsigned cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (sscape_type == MEDIA_FX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (irq == old_irq[cfg])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (irq == valid_irq[cfg])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return INVALID_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * Perform certain arcane port-checks to see whether there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * is a SoundScape board lurking behind the given ports.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static int detect_sscape(struct soundscape *s, long wss_io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) unsigned d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * The following code is lifted from the original OSS driver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * and as I don't have a datasheet I cannot really comment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * on what it is doing...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if ((inb(HOST_CTRL_IO(s->io_base)) & 0x78) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) d = inb(ODIE_ADDR_IO(s->io_base)) & 0xf0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if ((d & 0x80) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (d == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) s->ic_type = IC_ODIE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) else if ((d & 0x60) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) s->ic_type = IC_OPUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) outb(0xfa, ODIE_ADDR_IO(s->io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) outb(0xfe, ODIE_ADDR_IO(s->io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if ((inb(ODIE_ADDR_IO(s->io_base)) & 0x9f) != 0x0e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) outb(0xfe, ODIE_ADDR_IO(s->io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) d = inb(ODIE_DATA_IO(s->io_base));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (s->ic_type == IC_OPUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) activate_ad1845_unsafe(s->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (s->type == SSCAPE_VIVO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) wss_io += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* wait for WSS codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) for (d = 0; d < 500; d++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) if ((inb(wss_io) & 0x80) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if ((inb(wss_io) & 0x80) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (inb(wss_io + 2) == 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) goto _done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if ((inb(wss_io) & 0x80) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) s->type = MEDIA_FX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* wait for WSS codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) for (d = 0; d < 500; d++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if ((inb(wss_io) & 0x80) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) spin_lock_irqsave(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) * SoundScape successfully detected!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) retval = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) _done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) spin_unlock_irqrestore(&s->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * ALSA callback function, called when attempting to open the MIDI device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * Check that the MIDI firmware has been loaded, because we don't want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * to crash the machine. Also check that someone isn't using the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * IOCTL device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) static int mpu401_open(struct snd_mpu401 *mpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (!verify_mpu401(mpu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) snd_printk(KERN_ERR "sscape: MIDI disabled, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) "please load firmware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * Initialise an MPU-401 subdevice for MIDI support on the SoundScape.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static int create_mpu401(struct snd_card *card, int devnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) unsigned long port, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) struct soundscape *sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct snd_rawmidi *rawmidi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) MPU401_INFO_INTEGRATED, irq, &rawmidi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (err == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) struct snd_mpu401 *mpu = rawmidi->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) mpu->open_input = mpu401_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) mpu->open_output = mpu401_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) mpu->private_data = sscape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) initialise_mpu401(mpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * Create an AD1845 PCM subdevice on the SoundScape. The AD1845
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * is very much like a CS4231, with a few extra bits. We will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * try to support at least some of the extra bits by overriding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * some of the CS4231 callback.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static int create_ad1845(struct snd_card *card, unsigned port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int irq, int dma1, int dma2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) register struct soundscape *sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) struct snd_wss *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int codec_type = WSS_HW_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) switch (sscape->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) case MEDIA_FX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) case SSCAPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) * There are some freak examples of early Soundscape cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * with CS4231 instead of AD1848/CS4248. Unfortunately, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * CS4231 works only in CS4248 compatibility mode on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * these cards so force it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (sscape->ic_type != IC_OPUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) codec_type = WSS_HW_AD1848;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) case SSCAPE_VIVO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) port += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) err = snd_wss_create(card, port, -1, irq, dma1, dma2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) codec_type, WSS_HWSHARE_DMA1, &chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (sscape->type != SSCAPE_VIVO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * The input clock frequency on the SoundScape must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * be 14.31818 MHz, because we must set this register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * to get the playback to sound correct ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) snd_wss_mce_up(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) spin_lock_irqsave(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) snd_wss_out(chip, AD1845_CLOCK, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) spin_unlock_irqrestore(&chip->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) snd_wss_mce_down(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) err = snd_wss_pcm(chip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) snd_printk(KERN_ERR "sscape: No PCM device "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) "for AD1845 chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) goto _error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) err = snd_wss_mixer(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) snd_printk(KERN_ERR "sscape: No mixer device "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) "for AD1845 chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) goto _error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (chip->hardware != WSS_HW_AD1848) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) err = snd_wss_timer(chip, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) snd_printk(KERN_ERR "sscape: No timer device "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) "for AD1845 chip\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) goto _error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (sscape->type != SSCAPE_VIVO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) err = snd_ctl_add(card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) snd_ctl_new1(&midi_mixer_ctl, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) snd_printk(KERN_ERR "sscape: Could not create "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) "MIDI mixer control\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) goto _error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) sscape->chip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) _error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * Create an ALSA soundcard entry for the SoundScape, using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * the given list of port, IRQ and DMA resources.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) static int create_sscape(int dev, struct snd_card *card)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct soundscape *sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) unsigned dma_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) unsigned irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) unsigned mpu_irq_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) struct resource *io_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct resource *wss_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * Grab IO ports that we will need to probe so that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * can detect and control this hardware ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) io_res = request_region(port[dev], 8, "SoundScape");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (!io_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) snd_printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) "sscape: can't grab port 0x%lx\n", port[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) wss_res = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if (sscape->type == SSCAPE_VIVO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) wss_res = request_region(wss_port[dev], 4, "SoundScape");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (!wss_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) snd_printk(KERN_ERR "sscape: can't grab port 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) wss_port[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) goto _release_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * Grab one DMA channel ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) err = request_dma(dma[dev], "SoundScape");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) goto _release_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) spin_lock_init(&sscape->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) sscape->io_res = io_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) sscape->wss_res = wss_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) sscape->io_base = port[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (!detect_sscape(sscape, wss_port[dev])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) sscape->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) switch (sscape->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case MEDIA_FX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) name = "MediaFX/SoundFX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case SSCAPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) name = "Soundscape";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) case SSCAPE_PNP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) name = "Soundscape PnP";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) case SSCAPE_VIVO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) name = "Soundscape VIVO";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) name = "unknown Soundscape";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) name, sscape->io_base, irq[dev], dma[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * Check that the user didn't pass us garbage data ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) irq_cfg = get_irq_config(sscape->type, irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (irq_cfg == INVALID_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (mpu_irq_cfg == INVALID_IRQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) * Tell the on-board devices where their resources are (I think -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) * I can't be sure without a datasheet ... So many magic values!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) spin_lock_irqsave(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * Enable and configure the DMA channels ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) mpu_irq_cfg |= mpu_irq_cfg << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (joystick[dev])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) val |= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) sscape_write_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) GA_CDCFG_REG, 0x09 | DMA_8BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) | (dma[dev] << 4) | (irq_cfg << 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * Enable the master IRQ ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) spin_unlock_irqrestore(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * We have now enabled the codec chip, and so we should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * detect the AD1845 device ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) err = create_ad1845(card, wss_port[dev], irq[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) dma[dev], dma2[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) snd_printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) wss_port[dev], irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) strcpy(card->driver, "SoundScape");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) strcpy(card->shortname, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) name, sscape->chip->port, sscape->chip->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) sscape->chip->dma1, sscape->chip->dma2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) #define MIDI_DEVNUM 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (sscape->type != SSCAPE_VIVO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) err = sscape_upload_bootblock(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (err >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) err = sscape_upload_microcode(card, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (err == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) err = create_mpu401(card, MIDI_DEVNUM, port[dev],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) mpu_irq[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) snd_printk(KERN_ERR "sscape: Failed to create "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) "MPU-401 device at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) port[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) goto _release_dma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * Initialize mixer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) spin_lock_irqsave(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) sscape->midi_vol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) CMD_SET_MIDI_VOL, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) sscape->midi_vol, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) CMD_XXX_MIDI_VOL, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) sscape->midi_vol, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) CMD_SET_EXTMIDI, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) host_write_ctrl_unsafe(sscape->io_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 0, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) set_midi_mode_unsafe(sscape->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) spin_unlock_irqrestore(&sscape->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) * Now that we have successfully created this sound card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) * it is safe to store the pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) * NOTE: we only register the sound card's "destructor"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) * function now that our "constructor" has completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) card->private_free = soundscape_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) _release_dma:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) free_dma(dma[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) _release_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) release_and_free_resource(wss_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) release_and_free_resource(io_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) static int snd_sscape_match(struct device *pdev, unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) * Make sure we were given ALL of the other parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if (port[i] == SNDRV_AUTO_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (irq[i] == SNDRV_AUTO_IRQ ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) mpu_irq[i] == SNDRV_AUTO_IRQ ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) dma[i] == SNDRV_AUTO_DMA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) "sscape: insufficient parameters, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) "need IO, IRQ, MPU-IRQ and DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) static int snd_sscape_probe(struct device *pdev, unsigned int dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct soundscape *sscape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ret = snd_card_new(pdev, index[dev], id[dev], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) sizeof(struct soundscape), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) sscape->type = SSCAPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) dma[dev] &= 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) ret = create_sscape(dev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) goto _release_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ret = snd_card_register(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) goto _release_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) dev_set_drvdata(pdev, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) _release_card:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static int snd_sscape_remove(struct device *devptr, unsigned int dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) snd_card_free(dev_get_drvdata(devptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) #define DEV_NAME "sscape"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) static struct isa_driver snd_sscape_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) .match = snd_sscape_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) .probe = snd_sscape_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) .remove = snd_sscape_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) /* FIXME: suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) .name = DEV_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static inline int get_next_autoindex(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) ++i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) static int sscape_pnp_detect(struct pnp_card_link *pcard,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) const struct pnp_card_device_id *pid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) static int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) struct pnp_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct soundscape *sscape;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * Allow this function to fail *quietly* if all the ISA PnP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * devices were configured using module parameters instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) idx = get_next_autoindex(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (idx >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * Check that we still have room for another sound card ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (!pnp_is_active(dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (pnp_activate_dev(dev) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) snd_printk(KERN_INFO "sscape: device is inactive\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * Create a new ALSA sound card entry, in anticipation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * of detecting our hardware ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ret = snd_card_new(&pcard->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) index[idx], id[idx], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) sizeof(struct soundscape), &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) sscape = get_card_soundscape(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * Identify card model ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) if (!strncmp("ENS4081", pid->id, 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) sscape->type = SSCAPE_VIVO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) sscape->type = SSCAPE_PNP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * Read the correct parameters off the ISA PnP bus ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) port[idx] = pnp_port_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) irq[idx] = pnp_irq(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) mpu_irq[idx] = pnp_irq(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) dma[idx] = pnp_dma(dev, 0) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (sscape->type == SSCAPE_PNP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) dma2[idx] = dma[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) wss_port[idx] = CODEC_IO(port[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) wss_port[idx] = pnp_port_start(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) dma2[idx] = pnp_dma(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) ret = create_sscape(idx, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) goto _release_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) ret = snd_card_register(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) goto _release_card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) pnp_set_card_drvdata(pcard, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) ++idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) _release_card:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static void sscape_pnp_remove(struct pnp_card_link *pcard)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) snd_card_free(pnp_get_card_drvdata(pcard));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) pnp_set_card_drvdata(pcard, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) static struct pnp_card_driver sscape_pnpc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .name = "sscape",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .id_table = sscape_pnpids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .probe = sscape_pnp_detect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) .remove = sscape_pnp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) #endif /* CONFIG_PNP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static int __init sscape_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) err = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) isa_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) err = pnp_register_card_driver(&sscape_pnpc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) pnp_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (isa_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static void __exit sscape_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (pnp_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) pnp_unregister_card_driver(&sscape_pnpc_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (isa_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) isa_unregister_driver(&snd_sscape_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) module_init(sscape_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) module_exit(sscape_exit);