1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * digi00x-proc.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 | static int get_optical_iface_mode(struct snd_dg00x *dg00x, |
11 | enum snd_dg00x_optical_mode *mode) |
12 | { |
13 | __be32 data; |
14 | int err; |
15 | |
16 | err = snd_fw_transaction(unit: dg00x->unit, TCODE_READ_QUADLET_REQUEST, |
17 | DG00X_ADDR_BASE + DG00X_OFFSET_OPT_IFACE_MODE, |
18 | buffer: &data, length: sizeof(data), flags: 0); |
19 | if (err >= 0) |
20 | *mode = be32_to_cpu(data) & 0x01; |
21 | |
22 | return err; |
23 | } |
24 | |
25 | static void proc_read_clock(struct snd_info_entry *entry, |
26 | struct snd_info_buffer *buf) |
27 | { |
28 | static const char *const source_name[] = { |
29 | [SND_DG00X_CLOCK_INTERNAL] = "internal" , |
30 | [SND_DG00X_CLOCK_SPDIF] = "s/pdif" , |
31 | [SND_DG00X_CLOCK_ADAT] = "adat" , |
32 | [SND_DG00X_CLOCK_WORD] = "word clock" , |
33 | }; |
34 | static const char *const optical_name[] = { |
35 | [SND_DG00X_OPT_IFACE_MODE_ADAT] = "adat" , |
36 | [SND_DG00X_OPT_IFACE_MODE_SPDIF] = "s/pdif" , |
37 | }; |
38 | struct snd_dg00x *dg00x = entry->private_data; |
39 | enum snd_dg00x_optical_mode mode; |
40 | unsigned int rate; |
41 | enum snd_dg00x_clock clock; |
42 | bool detect; |
43 | |
44 | if (get_optical_iface_mode(dg00x, mode: &mode) < 0) |
45 | return; |
46 | if (snd_dg00x_stream_get_local_rate(dg00x, rate: &rate) < 0) |
47 | return; |
48 | if (snd_dg00x_stream_get_clock(dg00x, clock: &clock) < 0) |
49 | return; |
50 | |
51 | snd_iprintf(buf, "Optical mode: %s\n" , optical_name[mode]); |
52 | snd_iprintf(buf, "Sampling Rate: %d\n" , rate); |
53 | snd_iprintf(buf, "Clock Source: %s\n" , source_name[clock]); |
54 | |
55 | if (clock == SND_DG00X_CLOCK_INTERNAL) |
56 | return; |
57 | |
58 | if (snd_dg00x_stream_check_external_clock(dg00x, detect: &detect) < 0) |
59 | return; |
60 | snd_iprintf(buf, "External source: %s\n" , detect ? "detected" : "not" ); |
61 | if (!detect) |
62 | return; |
63 | |
64 | if (snd_dg00x_stream_get_external_rate(dg00x, rate: &rate) >= 0) |
65 | snd_iprintf(buf, "External sampling rate: %d\n" , rate); |
66 | } |
67 | |
68 | void snd_dg00x_proc_init(struct snd_dg00x *dg00x) |
69 | { |
70 | struct snd_info_entry *root, *entry; |
71 | |
72 | /* |
73 | * All nodes are automatically removed at snd_card_disconnect(), |
74 | * by following to link list. |
75 | */ |
76 | root = snd_info_create_card_entry(card: dg00x->card, name: "firewire" , |
77 | parent: dg00x->card->proc_root); |
78 | if (root == NULL) |
79 | return; |
80 | |
81 | root->mode = S_IFDIR | 0555; |
82 | |
83 | entry = snd_info_create_card_entry(card: dg00x->card, name: "clock" , parent: root); |
84 | if (entry) |
85 | snd_info_set_text_ops(entry, private_data: dg00x, read: proc_read_clock); |
86 | } |
87 | |