David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 2 | /* |
| 3 | * digi00x-proc.c - a part of driver for Digidesign Digi 002/003 family |
| 4 | * |
| 5 | * Copyright (c) 2014-2015 Takashi Sakamoto |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 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(dg00x->unit, TCODE_READ_QUADLET_REQUEST, |
| 17 | DG00X_ADDR_BASE + DG00X_OFFSET_OPT_IFACE_MODE, |
| 18 | &data, sizeof(data), 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) < 0) |
| 45 | return; |
| 46 | if (snd_dg00x_stream_get_local_rate(dg00x, &rate) < 0) |
| 47 | return; |
| 48 | if (snd_dg00x_stream_get_clock(dg00x, &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) < 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) >= 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(dg00x->card, "firewire", |
| 77 | dg00x->card->proc_root); |
| 78 | if (root == NULL) |
| 79 | return; |
| 80 | |
| 81 | root->mode = S_IFDIR | 0555; |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 82 | |
| 83 | entry = snd_info_create_card_entry(dg00x->card, "clock", root); |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame^] | 84 | if (entry) |
| 85 | snd_info_set_text_ops(entry, dg00x, proc_read_clock); |
Andrew Scull | b4b6d4a | 2019-01-02 15:54:55 +0000 | [diff] [blame] | 86 | } |