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