dice.c 7.3 KB
Newer Older
C
Clemens Ladisch 已提交
1 2 3 4 5 6 7
/*
 * TC Applied Technologies Digital Interface Communications Engine driver
 *
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 * Licensed under the terms of the GNU General Public License, version 2.
 */

8
#include "dice.h"
C
Clemens Ladisch 已提交
9 10 11 12 13

MODULE_DESCRIPTION("DICE driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");

14
#define OUI_WEISS		0x001c6a
15
#define OUI_LOUD		0x000ff2
16 17 18

#define DICE_CATEGORY_ID	0x04
#define WEISS_CATEGORY_ID	0x00
19
#define LOUD_CATEGORY_ID	0x10
20

21
static int check_dice_category(struct fw_unit *unit)
22 23 24
{
	struct fw_device *device = fw_parent_device(unit);
	struct fw_csr_iterator it;
25 26
	int key, val, vendor = -1, model = -1;
	unsigned int category;
27

28 29 30
	/*
	 * Check that GUID and unit directory are constructed according to DICE
	 * rules, i.e., that the specifier ID is the GUID's OUI, and that the
31 32
	 * GUID chip ID consists of the 8-bit category ID, the 10-bit product
	 * ID, and a 22-bit serial number.
33 34
	 */
	fw_csr_iterator_init(&it, unit->directory);
35
	while (fw_csr_iterator_next(&it, &key, &val)) {
36 37
		switch (key) {
		case CSR_SPECIFIER_ID:
38
			vendor = val;
39 40
			break;
		case CSR_MODEL:
41
			model = val;
42 43 44
			break;
		}
	}
45 46
	if (vendor == OUI_WEISS)
		category = WEISS_CATEGORY_ID;
47 48
	else if (vendor == OUI_LOUD)
		category = LOUD_CATEGORY_ID;
49 50 51
	else
		category = DICE_CATEGORY_ID;
	if (device->config_rom[3] != ((vendor << 8) | category) ||
52 53
	    device->config_rom[4] >> 22 != model)
		return -ENODEV;
54

55
	return 0;
56 57
}

58 59
static int highest_supported_mode_rate(struct snd_dice *dice,
				       unsigned int mode, unsigned int *rate)
60
{
61
	unsigned int i, m;
62

63 64 65 66 67 68 69 70 71
	for (i = ARRAY_SIZE(snd_dice_rates); i > 0; i--) {
		*rate = snd_dice_rates[i - 1];
		if (snd_dice_stream_get_rate_mode(dice, *rate, &m) < 0)
			continue;
		if (mode == m)
			break;
	}
	if (i == 0)
		return -EINVAL;
72

73
	return 0;
74 75
}

76
static int dice_read_mode_params(struct snd_dice *dice, unsigned int mode)
77 78
{
	__be32 values[2];
79 80
	unsigned int rate;
	int err;
81

82
	if (highest_supported_mode_rate(dice, mode, &rate) < 0) {
83 84
		dice->tx_channels[mode] = 0;
		dice->tx_midi_ports[mode] = 0;
85 86 87 88 89
		dice->rx_channels[mode] = 0;
		dice->rx_midi_ports[mode] = 0;
		return 0;
	}

90
	err = snd_dice_transaction_set_rate(dice, rate);
91 92 93
	if (err < 0)
		return err;

94 95 96 97 98 99 100 101
	err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO,
					   values, sizeof(values));
	if (err < 0)
		return err;

	dice->tx_channels[mode]   = be32_to_cpu(values[0]);
	dice->tx_midi_ports[mode] = be32_to_cpu(values[1]);

102 103
	err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO,
					   values, sizeof(values));
104 105 106 107 108 109 110 111 112
	if (err < 0)
		return err;

	dice->rx_channels[mode]   = be32_to_cpu(values[0]);
	dice->rx_midi_ports[mode] = be32_to_cpu(values[1]);

	return 0;
}

113
static int dice_read_params(struct snd_dice *dice)
C
Clemens Ladisch 已提交
114
{
115
	__be32 value;
116
	int mode, err;
C
Clemens Ladisch 已提交
117

118
	/* some very old firmwares don't tell about their clock support */
119 120 121 122
	if (dice->clock_caps > 0) {
		err = snd_dice_transaction_read_global(dice,
						GLOBAL_CLOCK_CAPABILITIES,
						&value, 4);
123 124 125 126 127 128 129 130 131 132 133
		if (err < 0)
			return err;
		dice->clock_caps = be32_to_cpu(value);
	} else {
		/* this should be supported by any device */
		dice->clock_caps = CLOCK_CAP_RATE_44100 |
				   CLOCK_CAP_RATE_48000 |
				   CLOCK_CAP_SOURCE_ARX1 |
				   CLOCK_CAP_SOURCE_INTERNAL;
	}

134 135 136 137 138 139
	for (mode = 2; mode >= 0; --mode) {
		err = dice_read_mode_params(dice, mode);
		if (err < 0)
			return err;
	}

C
Clemens Ladisch 已提交
140 141 142
	return 0;
}

143
static void dice_card_strings(struct snd_dice *dice)
C
Clemens Ladisch 已提交
144 145 146 147 148 149 150 151 152 153 154
{
	struct snd_card *card = dice->card;
	struct fw_device *dev = fw_parent_device(dice->unit);
	char vendor[32], model[32];
	unsigned int i;
	int err;

	strcpy(card->driver, "DICE");

	strcpy(card->shortname, "DICE");
	BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
155 156 157
	err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME,
					       card->shortname,
					       sizeof(card->shortname));
C
Clemens Ladisch 已提交
158 159 160 161 162 163 164 165 166 167 168 169 170
	if (err >= 0) {
		/* DICE strings are returned in "always-wrong" endianness */
		BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
		for (i = 0; i < sizeof(card->shortname); i += 4)
			swab32s((u32 *)&card->shortname[i]);
		card->shortname[sizeof(card->shortname) - 1] = '\0';
	}

	strcpy(vendor, "?");
	fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
	strcpy(model, "?");
	fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
	snprintf(card->longname, sizeof(card->longname),
171 172
		 "%s %s (serial %u) at %s, S%d",
		 vendor, model, dev->config_rom[4] & 0x3fffff,
C
Clemens Ladisch 已提交
173 174 175 176 177
		 dev_name(&dice->unit->device), 100 << dev->max_speed);

	strcpy(card->mixername, "DICE");
}

178 179 180 181 182 183
/*
 * This module releases the FireWire unit data after all ALSA character devices
 * are released by applications. This is for releasing stream data or finishing
 * transactions safely. Thus at returning from .remove(), this module still keep
 * references for the unit.
 */
184 185 186 187
static void dice_card_free(struct snd_card *card)
{
	struct snd_dice *dice = card->private_data;

188
	snd_dice_stream_destroy_duplex(dice);
189
	snd_dice_transaction_destroy(dice);
190 191
	fw_unit_put(dice->unit);

192 193 194
	mutex_destroy(&dice->mutex);
}

C
Clemens Ladisch 已提交
195 196 197
static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
{
	struct snd_card *card;
198
	struct snd_dice *dice;
C
Clemens Ladisch 已提交
199 200
	int err;

201
	err = check_dice_category(unit);
202
	if (err < 0)
203
		return -ENODEV;
204

205 206
	err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE,
			   sizeof(*dice), &card);
C
Clemens Ladisch 已提交
207
	if (err < 0)
208
		goto end;
C
Clemens Ladisch 已提交
209 210 211

	dice = card->private_data;
	dice->card = card;
212
	dice->unit = fw_unit_get(unit);
213 214
	card->private_free = dice_card_free;

215
	spin_lock_init(&dice->lock);
C
Clemens Ladisch 已提交
216
	mutex_init(&dice->mutex);
217
	init_completion(&dice->clock_accepted);
218
	init_waitqueue_head(&dice->hwdep_wait);
C
Clemens Ladisch 已提交
219

220
	err = snd_dice_transaction_init(dice);
C
Clemens Ladisch 已提交
221
	if (err < 0)
222
		goto error;
223 224 225

	err = dice_read_params(dice);
	if (err < 0)
226
		goto error;
C
Clemens Ladisch 已提交
227 228 229

	dice_card_strings(dice);

230
	err = snd_dice_create_pcm(dice);
C
Clemens Ladisch 已提交
231 232 233
	if (err < 0)
		goto error;

234
	err = snd_dice_create_hwdep(dice);
C
Clemens Ladisch 已提交
235 236 237
	if (err < 0)
		goto error;

238
	snd_dice_create_proc(dice);
239

240 241 242 243
	err = snd_dice_create_midi(dice);
	if (err < 0)
		goto error;

244
	err = snd_dice_stream_init_duplex(dice);
C
Clemens Ladisch 已提交
245 246 247
	if (err < 0)
		goto error;

248 249
	err = snd_card_register(card);
	if (err < 0) {
250
		snd_dice_stream_destroy_duplex(dice);
251 252
		goto error;
	}
C
Clemens Ladisch 已提交
253

254 255 256
	dev_set_drvdata(&unit->device, dice);
end:
	return err;
C
Clemens Ladisch 已提交
257 258 259 260 261 262 263
error:
	snd_card_free(card);
	return err;
}

static void dice_remove(struct fw_unit *unit)
{
264
	struct snd_dice *dice = dev_get_drvdata(&unit->device);
C
Clemens Ladisch 已提交
265

266
	/* No need to wait for releasing card object in this context. */
C
Clemens Ladisch 已提交
267 268 269 270 271
	snd_card_free_when_closed(dice->card);
}

static void dice_bus_reset(struct fw_unit *unit)
{
272
	struct snd_dice *dice = dev_get_drvdata(&unit->device);
C
Clemens Ladisch 已提交
273

274 275 276
	/* The handler address register becomes initialized. */
	snd_dice_transaction_reinit(dice);

S
Stefan Richter 已提交
277
	mutex_lock(&dice->mutex);
278
	snd_dice_stream_update_duplex(dice);
C
Clemens Ladisch 已提交
279 280 281 282 283 284 285
	mutex_unlock(&dice->mutex);
}

#define DICE_INTERFACE	0x000001

static const struct ieee1394_device_id dice_id_table[] = {
	{
286 287
		.match_flags = IEEE1394_MATCH_VERSION,
		.version     = DICE_INTERFACE,
C
Clemens Ladisch 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
	},
	{ }
};
MODULE_DEVICE_TABLE(ieee1394, dice_id_table);

static struct fw_driver dice_driver = {
	.driver   = {
		.owner	= THIS_MODULE,
		.name	= KBUILD_MODNAME,
		.bus	= &fw_bus_type,
	},
	.probe    = dice_probe,
	.update   = dice_bus_reset,
	.remove   = dice_remove,
	.id_table = dice_id_table,
};

static int __init alsa_dice_init(void)
{
	return driver_register(&dice_driver.driver);
}

static void __exit alsa_dice_exit(void)
{
	driver_unregister(&dice_driver.driver);
}

module_init(alsa_dice_init);
module_exit(alsa_dice_exit);