Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c2bc7c7 authored by Adrian Knoth's avatar Adrian Knoth Committed by Takashi Iwai
Browse files

ALSA: hdsp - Fix detection for RME RPM/Multiface/Digiface ioboxes



The current iobox detection code reportedly fails for various users, so
simply do what the Win32 driver does instead.

Patch originally by Karl Grill <kgrill@chello.at> and then modified to
comply with kernel coding guidelines + current HEAD.

Signed-off-by: default avatarAdrian Knoth <adi@drcomp.erfurt.thur.de>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 6ab31741
Loading
Loading
Loading
Loading
+65 −26
Original line number Diff line number Diff line
@@ -154,10 +154,13 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
#define HDSP_BIGENDIAN_MODE     0x200
#define HDSP_RD_MULTIPLE        0x400
#define HDSP_9652_ENABLE_MIXER  0x800
#define HDSP_S200		0x800
#define HDSP_S300		(0x100 | HDSP_S200) /* dummy, purpose of 0x100 unknown */
#define HDSP_CYCLIC_MODE	0x1000
#define HDSP_TDO                0x10000000

#define HDSP_S_PROGRAM     	(HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
#define HDSP_S_LOAD		(HDSP_PROGRAM|HDSP_CONFIG_MODE_1)
#define HDSP_S_PROGRAM	    (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_0)
#define HDSP_S_LOAD	    (HDSP_CYCLIC_MODE|HDSP_PROGRAM|HDSP_CONFIG_MODE_1)

/* Control Register bits */

@@ -671,14 +674,24 @@ static unsigned int hdsp_read(struct hdsp *hdsp, int reg)

static int hdsp_check_for_iobox (struct hdsp *hdsp)
{
	int i;

	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
	if (hdsp_read (hdsp, HDSP_statusRegister) & HDSP_ConfigError) {
		snd_printk("Hammerfall-DSP: no IO box connected!\n");
		hdsp->state &= ~HDSP_FirmwareLoaded;
		return -EIO;
	for (i = 0; i < 500; i++) {
		if (0 == (hdsp_read(hdsp, HDSP_statusRegister) &
					HDSP_ConfigError)) {
			if (i) {
				snd_printd("Hammerfall-DSP: IO box found after %d ms\n",
						(20 * i));
			}
			return 0;
		}
		msleep(20);
	}
	snd_printk(KERN_ERR "Hammerfall-DSP: no IO box connected!\n");
	hdsp->state &= ~HDSP_FirmwareLoaded;
	return -EIO;
}

static int hdsp_wait_for_iobox(struct hdsp *hdsp, unsigned int loops,
			       unsigned int delay)
@@ -728,6 +741,7 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {

		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
			snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
			hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
			return -EIO;
		}

@@ -737,17 +751,15 @@ static int snd_hdsp_load_firmware_from_cache(struct hdsp *hdsp) {
			hdsp_write(hdsp, HDSP_fifoData, cache[i]);
			if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
				snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
				hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);
				return -EIO;
			}
		}

		ssleep(3);

		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
			snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
		    	return -EIO;
		}
		hdsp_fifo_wait(hdsp, 3, HDSP_LONG_WAIT);
		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200);

		ssleep(3);
#ifdef SNDRV_BIG_ENDIAN
		hdsp->control2_register = HDSP_BIGENDIAN_MODE;
#else
@@ -773,24 +785,51 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp)
{
	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {

		hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
		hdsp_write(hdsp, HDSP_fifoData, 0);
		if (hdsp_fifo_wait (hdsp, 0, HDSP_SHORT_WAIT) < 0)
			return -EIO;

		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
			hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
			hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
		}

		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S200 | HDSP_PROGRAM);
		hdsp_write (hdsp, HDSP_fifoData, 0);
		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
			hdsp->io_type = Multiface;
			snd_printk("Hammerfall-DSP: Multiface found\n");
			return 0;
		}

		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT)) {
			hdsp_write(hdsp, HDSP_control2Reg, HDSP_VERSION_BIT);
		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
			if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT))
				hdsp->io_type = RPM;
			else
				hdsp->io_type = Multiface;
		} else {
		hdsp_write(hdsp, HDSP_fifoData, 0);
		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
			hdsp->io_type = Digiface;
			snd_printk("Hammerfall-DSP: Digiface found\n");
			return 0;
		}

		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
		hdsp_write(hdsp, HDSP_fifoData, 0);
		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) == 0) {
			hdsp->io_type = Multiface;
			snd_printk("Hammerfall-DSP: Multiface found\n");
			return 0;
		}

		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S300);
		hdsp_write(hdsp, HDSP_control2Reg, HDSP_S_LOAD);
		hdsp_write(hdsp, HDSP_fifoData, 0);
		if (hdsp_fifo_wait(hdsp, 0, HDSP_SHORT_WAIT) < 0) {
			hdsp->io_type = Multiface;
			snd_printk("Hammerfall-DSP: Multiface found\n");
			return 0;
		}

		hdsp->io_type = RPM;
		snd_printk("Hammerfall-DSP: RPM found\n");
		return 0;
	} else {
		/* firmware was already loaded, get iobox type */
		if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version2)