Takashi Sakamoto | 927f17d | 2015-09-30 09:39:19 +0900 | [diff] [blame] | 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 | } |