Commit | Line | Data |
---|---|---|
927f17dc TS |
1 | /* |
2 | * digi00x-proc.c - a part of driver for Digidesign Digi 002/003 family | |
3 | * | |
4 | * Copyright (c) 2014-2015 Takashi Sakamoto | |
5 | * | |
6 | * Licensed under the terms of the GNU General Public License, version 2. | |
7 | */ | |
8 | ||
9 | #include "digi00x.h" | |
10 | ||
11 | static int get_optical_iface_mode(struct snd_dg00x *dg00x, | |
12 | enum snd_dg00x_optical_mode *mode) | |
13 | { | |
14 | __be32 data; | |
15 | int err; | |
16 | ||
17 | err = snd_fw_transaction(dg00x->unit, TCODE_READ_QUADLET_REQUEST, | |
18 | DG00X_ADDR_BASE + DG00X_OFFSET_OPT_IFACE_MODE, | |
19 | &data, sizeof(data), 0); | |
20 | if (err >= 0) | |
21 | *mode = be32_to_cpu(data) & 0x01; | |
22 | ||
23 | return err; | |
24 | } | |
25 | ||
26 | static void proc_read_clock(struct snd_info_entry *entry, | |
27 | struct snd_info_buffer *buf) | |
28 | { | |
29 | static const char *const source_name[] = { | |
30 | [SND_DG00X_CLOCK_INTERNAL] = "internal", | |
31 | [SND_DG00X_CLOCK_SPDIF] = "s/pdif", | |
32 | [SND_DG00X_CLOCK_ADAT] = "adat", | |
33 | [SND_DG00X_CLOCK_WORD] = "word clock", | |
34 | }; | |
35 | static const char *const optical_name[] = { | |
36 | [SND_DG00X_OPT_IFACE_MODE_ADAT] = "adat", | |
37 | [SND_DG00X_OPT_IFACE_MODE_SPDIF] = "s/pdif", | |
38 | }; | |
39 | struct snd_dg00x *dg00x = entry->private_data; | |
40 | enum snd_dg00x_optical_mode mode; | |
41 | unsigned int rate; | |
42 | enum snd_dg00x_clock clock; | |
43 | bool detect; | |
44 | ||
45 | if (get_optical_iface_mode(dg00x, &mode) < 0) | |
46 | return; | |
47 | if (snd_dg00x_stream_get_local_rate(dg00x, &rate) < 0) | |
48 | return; | |
49 | if (snd_dg00x_stream_get_clock(dg00x, &clock) < 0) | |
50 | return; | |
51 | ||
52 | snd_iprintf(buf, "Optical mode: %s\n", optical_name[mode]); | |
53 | snd_iprintf(buf, "Sampling Rate: %d\n", rate); | |
54 | snd_iprintf(buf, "Clock Source: %s\n", source_name[clock]); | |
55 | ||
56 | if (clock == SND_DG00X_CLOCK_INTERNAL) | |
57 | return; | |
58 | ||
59 | if (snd_dg00x_stream_check_external_clock(dg00x, &detect) < 0) | |
60 | return; | |
61 | snd_iprintf(buf, "External source: %s\n", detect ? "detected" : "not"); | |
62 | if (!detect) | |
63 | return; | |
64 | ||
65 | if (snd_dg00x_stream_get_external_rate(dg00x, &rate) >= 0) | |
66 | snd_iprintf(buf, "External sampling rate: %d\n", rate); | |
67 | } | |
68 | ||
69 | void snd_dg00x_proc_init(struct snd_dg00x *dg00x) | |
70 | { | |
71 | struct snd_info_entry *root, *entry; | |
72 | ||
73 | /* | |
74 | * All nodes are automatically removed at snd_card_disconnect(), | |
75 | * by following to link list. | |
76 | */ | |
77 | root = snd_info_create_card_entry(dg00x->card, "firewire", | |
78 | dg00x->card->proc_root); | |
79 | if (root == NULL) | |
80 | return; | |
81 | ||
82 | root->mode = S_IFDIR | S_IRUGO | S_IXUGO; | |
83 | if (snd_info_register(root) < 0) { | |
84 | snd_info_free_entry(root); | |
85 | return; | |
86 | } | |
87 | ||
88 | entry = snd_info_create_card_entry(dg00x->card, "clock", root); | |
89 | if (entry == NULL) { | |
90 | snd_info_free_entry(root); | |
91 | return; | |
92 | } | |
93 | ||
94 | snd_info_set_text_ops(entry, dg00x, proc_read_clock); | |
95 | if (snd_info_register(entry) < 0) { | |
96 | snd_info_free_entry(entry); | |
97 | snd_info_free_entry(root); | |
98 | } | |
99 | } |