Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/bebob/bebob_proc.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* bebob_proc.c - a part of driver for BeBoB based devices
4
*
5
* Copyright (c) 2013-2014 Takashi Sakamoto
6
*/
7
8
#include "./bebob.h"
9
10
/* contents of information register */
11
struct hw_info {
12
u64 manufacturer;
13
u32 protocol_ver;
14
u32 bld_ver;
15
u32 guid[2];
16
u32 model_id;
17
u32 model_rev;
18
u64 fw_date;
19
u64 fw_time;
20
u32 fw_id;
21
u32 fw_ver;
22
u32 base_addr;
23
u32 max_size;
24
u64 bld_date;
25
u64 bld_time;
26
/* may not used in product
27
u64 dbg_date;
28
u64 dbg_time;
29
u32 dbg_id;
30
u32 dbg_version;
31
*/
32
} __packed;
33
34
static void
35
proc_read_hw_info(struct snd_info_entry *entry,
36
struct snd_info_buffer *buffer)
37
{
38
struct snd_bebob *bebob = entry->private_data;
39
struct hw_info *info;
40
41
info = kzalloc(sizeof(struct hw_info), GFP_KERNEL);
42
if (info == NULL)
43
return;
44
45
if (snd_bebob_read_block(bebob->unit, 0,
46
info, sizeof(struct hw_info)) < 0)
47
goto end;
48
49
snd_iprintf(buffer, "Manufacturer:\t%.8s\n",
50
(char *)&info->manufacturer);
51
snd_iprintf(buffer, "Protocol Ver:\t%d\n", info->protocol_ver);
52
snd_iprintf(buffer, "Build Ver:\t%d\n", info->bld_ver);
53
snd_iprintf(buffer, "GUID:\t\t0x%.8X%.8X\n",
54
info->guid[0], info->guid[1]);
55
snd_iprintf(buffer, "Model ID:\t0x%02X\n", info->model_id);
56
snd_iprintf(buffer, "Model Rev:\t%d\n", info->model_rev);
57
snd_iprintf(buffer, "Firmware Date:\t%.8s\n", (char *)&info->fw_date);
58
snd_iprintf(buffer, "Firmware Time:\t%.8s\n", (char *)&info->fw_time);
59
snd_iprintf(buffer, "Firmware ID:\t0x%X\n", info->fw_id);
60
snd_iprintf(buffer, "Firmware Ver:\t%d\n", info->fw_ver);
61
snd_iprintf(buffer, "Base Addr:\t0x%X\n", info->base_addr);
62
snd_iprintf(buffer, "Max Size:\t%d\n", info->max_size);
63
snd_iprintf(buffer, "Loader Date:\t%.8s\n", (char *)&info->bld_date);
64
snd_iprintf(buffer, "Loader Time:\t%.8s\n", (char *)&info->bld_time);
65
66
end:
67
kfree(info);
68
}
69
70
static void
71
proc_read_meters(struct snd_info_entry *entry,
72
struct snd_info_buffer *buffer)
73
{
74
struct snd_bebob *bebob = entry->private_data;
75
const struct snd_bebob_meter_spec *spec = bebob->spec->meter;
76
u32 *buf;
77
unsigned int i, c, channels, size;
78
79
if (spec == NULL)
80
return;
81
82
channels = spec->num * 2;
83
size = channels * sizeof(u32);
84
buf = kmalloc(size, GFP_KERNEL);
85
if (buf == NULL)
86
return;
87
88
if (spec->get(bebob, buf, size) < 0)
89
goto end;
90
91
for (i = 0, c = 1; i < channels; i++) {
92
snd_iprintf(buffer, "%s %d:\t%d\n",
93
spec->labels[i / 2], c++, buf[i]);
94
if ((i + 1 < channels - 1) &&
95
(strcmp(spec->labels[i / 2],
96
spec->labels[(i + 1) / 2]) != 0))
97
c = 1;
98
}
99
end:
100
kfree(buf);
101
}
102
103
static void
104
proc_read_formation(struct snd_info_entry *entry,
105
struct snd_info_buffer *buffer)
106
{
107
struct snd_bebob *bebob = entry->private_data;
108
struct snd_bebob_stream_formation *formation;
109
unsigned int i;
110
111
snd_iprintf(buffer, "Output Stream from device:\n");
112
snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
113
formation = bebob->tx_stream_formations;
114
for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
115
snd_iprintf(buffer,
116
"\t%d\t%d\t%d\n", snd_bebob_rate_table[i],
117
formation[i].pcm, formation[i].midi);
118
}
119
120
snd_iprintf(buffer, "Input Stream to device:\n");
121
snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
122
formation = bebob->rx_stream_formations;
123
for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
124
snd_iprintf(buffer,
125
"\t%d\t%d\t%d\n", snd_bebob_rate_table[i],
126
formation[i].pcm, formation[i].midi);
127
}
128
}
129
130
static void
131
proc_read_clock(struct snd_info_entry *entry,
132
struct snd_info_buffer *buffer)
133
{
134
static const char *const clk_labels[] = {
135
"Internal",
136
"External",
137
"SYT-Match",
138
};
139
struct snd_bebob *bebob = entry->private_data;
140
const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate;
141
const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock;
142
enum snd_bebob_clock_type src;
143
unsigned int rate;
144
145
if (rate_spec->get(bebob, &rate) >= 0)
146
snd_iprintf(buffer, "Sampling rate: %d\n", rate);
147
148
if (snd_bebob_stream_get_clock_src(bebob, &src) >= 0) {
149
if (clk_spec)
150
snd_iprintf(buffer, "Clock Source: %s\n",
151
clk_labels[src]);
152
else
153
snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n",
154
clk_labels[src], bebob->sync_input_plug);
155
}
156
}
157
158
static void
159
add_node(struct snd_bebob *bebob, struct snd_info_entry *root, const char *name,
160
void (*op)(struct snd_info_entry *e, struct snd_info_buffer *b))
161
{
162
struct snd_info_entry *entry;
163
164
entry = snd_info_create_card_entry(bebob->card, name, root);
165
if (entry)
166
snd_info_set_text_ops(entry, bebob, op);
167
}
168
169
void snd_bebob_proc_init(struct snd_bebob *bebob)
170
{
171
struct snd_info_entry *root;
172
173
/*
174
* All nodes are automatically removed at snd_card_disconnect(),
175
* by following to link list.
176
*/
177
root = snd_info_create_card_entry(bebob->card, "firewire",
178
bebob->card->proc_root);
179
if (root == NULL)
180
return;
181
root->mode = S_IFDIR | 0555;
182
183
add_node(bebob, root, "clock", proc_read_clock);
184
add_node(bebob, root, "firmware", proc_read_hw_info);
185
add_node(bebob, root, "formation", proc_read_formation);
186
187
if (bebob->spec->meter != NULL)
188
add_node(bebob, root, "meter", proc_read_meters);
189
}
190
191