Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: dice: improve support for ancient firmware for DICE

In early stage of firmware SDK, DICE seems to lose its backward
compatibility due to some registers on global address section. I found
this with Alesis Multimix 12 FireWire with ancient firmware (approx.
shipped version).

According to retrieved log from the unit, global section has 96 byte
space. On the other hand, current version of ALSA dice driver assumes
that all of supported unit has at least 100 byte space.

$ ./firewire-request /dev/fw1 read 0xffffe0000000 28
result: 000: 00 00 00 0a 00 00 00 18 00 00 00 22 00 00 00 8a
result: 010: 00 00 00 ac 00 00 01 12 00 00 00 00 00 00 00 00
result: 020: 00 00 00 00 00 00 00 00

This commit adds support for the ancient firmware. Check of global section
is loosened to accept the smaller space. The lack of information is
already compensated by hard-coded parameters.

I experienced that the latest version of Windows driver for this model
can't handle this unit, too. This means that TCAT releases firmware SDK
without backward compatibility for the ancient firmware.

Below list is a early history of driver/firmware package released by
Alesis. I investigated on wayback machine on Internet Archive:
* Unknown: PAL v1.0.41.2, firmware v1.0.3
* Mar 2006: PAL v1.54.0, firmware v1.0.4
* Dec 2006: PAL v2.0.0.2, firmware v2.0
* Jun 2007: PAL v3.0.41.5, firmware v2.0
* Jul 2007: PAL v3.0.56.2. firmware v2.0
* Jan 2008: PAL v3.0.81.1080, firmware v2.0

If I can assume that firmware version is the same as DICE version, DICE
version for the issued firmware may be v1.0.3. According to code base of
userspace driver project (FFADO), I can read DICE v1.0.4 supports global
space larger than 100 byte. I guess the smaller space of global section is
a feature of DICE v1.0.3.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Takashi Sakamoto and committed by
Takashi Iwai
c1a36101 a9c2dfc8

+40 -28
+7 -2
sound/firewire/dice/dice-interface.h
··· 175 175 #define GLOBAL_SAMPLE_RATE 0x05c 176 176 177 177 /* 178 + * Some old firmware versions do not have the following global registers. 179 + * Windows drivers produced by TCAT lost backward compatibility in its 180 + * early release because they can handle firmware only which supports the 181 + * following registers. 182 + */ 183 + 184 + /* 178 185 * The version of the DICE driver specification that this device conforms to; 179 186 * read-only. 180 187 */ 181 188 #define GLOBAL_VERSION 0x060 182 - 183 - /* Some old firmware versions do not have the following global registers: */ 184 189 185 190 /* 186 191 * Supported sample rates and clock sources; read-only.
+5 -5
sound/firewire/dice/dice-proc.c
··· 148 148 >> CLOCK_RATE_SHIFT)); 149 149 snd_iprintf(buffer, " ext status: %08x\n", buf.global.extended_status); 150 150 snd_iprintf(buffer, " sample rate: %u\n", buf.global.sample_rate); 151 - snd_iprintf(buffer, " version: %u.%u.%u.%u\n", 152 - (buf.global.version >> 24) & 0xff, 153 - (buf.global.version >> 16) & 0xff, 154 - (buf.global.version >> 8) & 0xff, 155 - (buf.global.version >> 0) & 0xff); 156 151 if (quadlets >= 90) { 152 + snd_iprintf(buffer, " version: %u.%u.%u.%u\n", 153 + (buf.global.version >> 24) & 0xff, 154 + (buf.global.version >> 16) & 0xff, 155 + (buf.global.version >> 8) & 0xff, 156 + (buf.global.version >> 0) & 0xff); 157 157 snd_iprintf(buffer, " clock caps:"); 158 158 for (i = 0; i <= 6; ++i) 159 159 if (buf.global.clock_caps & (1 << i))
+28 -21
sound/firewire/dice/dice-transaction.c
··· 265 265 static int get_subaddrs(struct snd_dice *dice) 266 266 { 267 267 static const int min_values[10] = { 268 - 10, 0x64 / 4, 268 + 10, 0x60 / 4, 269 269 10, 0x18 / 4, 270 270 10, 0x18 / 4, 271 271 0, 0, ··· 301 301 } 302 302 } 303 303 304 - /* 305 - * Check that the implemented DICE driver specification major version 306 - * number matches. 307 - */ 308 - err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, 309 - DICE_PRIVATE_SPACE + 310 - be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, 311 - &version, sizeof(version), 0); 312 - if (err < 0) 313 - goto end; 304 + if (be32_to_cpu(pointers[1]) > 0x18) { 305 + /* 306 + * Check that the implemented DICE driver specification major 307 + * version number matches. 308 + */ 309 + err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST, 310 + DICE_PRIVATE_SPACE + 311 + be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION, 312 + &version, sizeof(version), 0); 313 + if (err < 0) 314 + goto end; 314 315 315 - if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) { 316 - dev_err(&dice->unit->device, 317 - "unknown DICE version: 0x%08x\n", be32_to_cpu(version)); 318 - err = -ENODEV; 319 - goto end; 316 + if ((version & cpu_to_be32(0xff000000)) != 317 + cpu_to_be32(0x01000000)) { 318 + dev_err(&dice->unit->device, 319 + "unknown DICE version: 0x%08x\n", 320 + be32_to_cpu(version)); 321 + err = -ENODEV; 322 + goto end; 323 + } 324 + 325 + /* Set up later. */ 326 + dice->clock_caps = 1; 320 327 } 321 328 322 329 dice->global_offset = be32_to_cpu(pointers[0]) * 4; 323 330 dice->tx_offset = be32_to_cpu(pointers[2]) * 4; 324 331 dice->rx_offset = be32_to_cpu(pointers[4]) * 4; 325 - dice->sync_offset = be32_to_cpu(pointers[6]) * 4; 326 - dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4; 327 332 328 - /* Set up later. */ 329 - if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4) 330 - dice->clock_caps = 1; 333 + /* Old firmware doesn't support these fields. */ 334 + if (pointers[7]) 335 + dice->sync_offset = be32_to_cpu(pointers[6]) * 4; 336 + if (pointers[9]) 337 + dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4; 331 338 end: 332 339 kfree(pointers); 333 340 return err;