Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/digi00x/digi00x.c
26451 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* digi00x.c - a part of driver for Digidesign Digi 002/003 family
4
*
5
* Copyright (c) 2014-2015 Takashi Sakamoto
6
*/
7
8
#include "digi00x.h"
9
10
MODULE_DESCRIPTION("Digidesign Digi 002/003 family Driver");
11
MODULE_AUTHOR("Takashi Sakamoto <[email protected]>");
12
MODULE_LICENSE("GPL");
13
14
#define VENDOR_DIGIDESIGN 0x00a07e
15
#define MODEL_CONSOLE 0x000001
16
#define MODEL_RACK 0x000002
17
#define SPEC_VERSION 0x000001
18
19
static int name_card(struct snd_dg00x *dg00x)
20
{
21
struct fw_device *fw_dev = fw_parent_device(dg00x->unit);
22
char name[32] = {0};
23
char *model;
24
int err;
25
26
err = fw_csr_string(dg00x->unit->directory, CSR_MODEL, name,
27
sizeof(name));
28
if (err < 0)
29
return err;
30
31
model = skip_spaces(name);
32
33
strscpy(dg00x->card->driver, "Digi00x");
34
strscpy(dg00x->card->shortname, model);
35
strscpy(dg00x->card->mixername, model);
36
snprintf(dg00x->card->longname, sizeof(dg00x->card->longname),
37
"Digidesign %s, GUID %08x%08x at %s, S%d", model,
38
fw_dev->config_rom[3], fw_dev->config_rom[4],
39
dev_name(&dg00x->unit->device), 100 << fw_dev->max_speed);
40
41
return 0;
42
}
43
44
static void dg00x_card_free(struct snd_card *card)
45
{
46
struct snd_dg00x *dg00x = card->private_data;
47
48
snd_dg00x_stream_destroy_duplex(dg00x);
49
snd_dg00x_transaction_unregister(dg00x);
50
51
mutex_destroy(&dg00x->mutex);
52
fw_unit_put(dg00x->unit);
53
}
54
55
static int snd_dg00x_probe(struct fw_unit *unit, const struct ieee1394_device_id *entry)
56
{
57
struct snd_card *card;
58
struct snd_dg00x *dg00x;
59
int err;
60
61
err = snd_card_new(&unit->device, -1, NULL, THIS_MODULE, sizeof(*dg00x), &card);
62
if (err < 0)
63
return err;
64
card->private_free = dg00x_card_free;
65
66
dg00x = card->private_data;
67
dg00x->unit = fw_unit_get(unit);
68
dev_set_drvdata(&unit->device, dg00x);
69
dg00x->card = card;
70
71
mutex_init(&dg00x->mutex);
72
spin_lock_init(&dg00x->lock);
73
init_waitqueue_head(&dg00x->hwdep_wait);
74
75
dg00x->is_console = entry->model_id == MODEL_CONSOLE;
76
77
err = name_card(dg00x);
78
if (err < 0)
79
goto error;
80
81
err = snd_dg00x_stream_init_duplex(dg00x);
82
if (err < 0)
83
goto error;
84
85
snd_dg00x_proc_init(dg00x);
86
87
err = snd_dg00x_create_pcm_devices(dg00x);
88
if (err < 0)
89
goto error;
90
91
err = snd_dg00x_create_midi_devices(dg00x);
92
if (err < 0)
93
goto error;
94
95
err = snd_dg00x_create_hwdep_device(dg00x);
96
if (err < 0)
97
goto error;
98
99
err = snd_dg00x_transaction_register(dg00x);
100
if (err < 0)
101
goto error;
102
103
err = snd_card_register(card);
104
if (err < 0)
105
goto error;
106
107
return 0;
108
error:
109
snd_card_free(card);
110
return err;
111
}
112
113
static void snd_dg00x_update(struct fw_unit *unit)
114
{
115
struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
116
117
snd_dg00x_transaction_reregister(dg00x);
118
119
mutex_lock(&dg00x->mutex);
120
snd_dg00x_stream_update_duplex(dg00x);
121
mutex_unlock(&dg00x->mutex);
122
}
123
124
static void snd_dg00x_remove(struct fw_unit *unit)
125
{
126
struct snd_dg00x *dg00x = dev_get_drvdata(&unit->device);
127
128
// Block till all of ALSA character devices are released.
129
snd_card_free(dg00x->card);
130
}
131
132
static const struct ieee1394_device_id snd_dg00x_id_table[] = {
133
/* Both of 002/003 use the same ID. */
134
{
135
.match_flags = IEEE1394_MATCH_VENDOR_ID |
136
IEEE1394_MATCH_VERSION |
137
IEEE1394_MATCH_MODEL_ID,
138
.vendor_id = VENDOR_DIGIDESIGN,
139
.version = SPEC_VERSION,
140
.model_id = MODEL_CONSOLE,
141
},
142
{
143
.match_flags = IEEE1394_MATCH_VENDOR_ID |
144
IEEE1394_MATCH_VERSION |
145
IEEE1394_MATCH_MODEL_ID,
146
.vendor_id = VENDOR_DIGIDESIGN,
147
.version = SPEC_VERSION,
148
.model_id = MODEL_RACK,
149
},
150
{}
151
};
152
MODULE_DEVICE_TABLE(ieee1394, snd_dg00x_id_table);
153
154
static struct fw_driver dg00x_driver = {
155
.driver = {
156
.owner = THIS_MODULE,
157
.name = KBUILD_MODNAME,
158
.bus = &fw_bus_type,
159
},
160
.probe = snd_dg00x_probe,
161
.update = snd_dg00x_update,
162
.remove = snd_dg00x_remove,
163
.id_table = snd_dg00x_id_table,
164
};
165
166
static int __init snd_dg00x_init(void)
167
{
168
return driver_register(&dg00x_driver.driver);
169
}
170
171
static void __exit snd_dg00x_exit(void)
172
{
173
driver_unregister(&dg00x_driver.driver);
174
}
175
176
module_init(snd_dg00x_init);
177
module_exit(snd_dg00x_exit);
178
179