Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * bebob_proc.c - a part of driver for BeBoB based devices
0004  *
0005  * Copyright (c) 2013-2014 Takashi Sakamoto
0006  */
0007 
0008 #include "./bebob.h"
0009 
0010 /* contents of information register */
0011 struct hw_info {
0012     u64 manufacturer;
0013     u32 protocol_ver;
0014     u32 bld_ver;
0015     u32 guid[2];
0016     u32 model_id;
0017     u32 model_rev;
0018     u64 fw_date;
0019     u64 fw_time;
0020     u32 fw_id;
0021     u32 fw_ver;
0022     u32 base_addr;
0023     u32 max_size;
0024     u64 bld_date;
0025     u64 bld_time;
0026 /* may not used in product
0027     u64 dbg_date;
0028     u64 dbg_time;
0029     u32 dbg_id;
0030     u32 dbg_version;
0031 */
0032 } __packed;
0033 
0034 static void
0035 proc_read_hw_info(struct snd_info_entry *entry,
0036           struct snd_info_buffer *buffer)
0037 {
0038     struct snd_bebob *bebob = entry->private_data;
0039     struct hw_info *info;
0040 
0041     info = kzalloc(sizeof(struct hw_info), GFP_KERNEL);
0042     if (info == NULL)
0043         return;
0044 
0045     if (snd_bebob_read_block(bebob->unit, 0,
0046                    info, sizeof(struct hw_info)) < 0)
0047         goto end;
0048 
0049     snd_iprintf(buffer, "Manufacturer:\t%.8s\n",
0050             (char *)&info->manufacturer);
0051     snd_iprintf(buffer, "Protocol Ver:\t%d\n", info->protocol_ver);
0052     snd_iprintf(buffer, "Build Ver:\t%d\n", info->bld_ver);
0053     snd_iprintf(buffer, "GUID:\t\t0x%.8X%.8X\n",
0054             info->guid[0], info->guid[1]);
0055     snd_iprintf(buffer, "Model ID:\t0x%02X\n", info->model_id);
0056     snd_iprintf(buffer, "Model Rev:\t%d\n", info->model_rev);
0057     snd_iprintf(buffer, "Firmware Date:\t%.8s\n", (char *)&info->fw_date);
0058     snd_iprintf(buffer, "Firmware Time:\t%.8s\n", (char *)&info->fw_time);
0059     snd_iprintf(buffer, "Firmware ID:\t0x%X\n", info->fw_id);
0060     snd_iprintf(buffer, "Firmware Ver:\t%d\n", info->fw_ver);
0061     snd_iprintf(buffer, "Base Addr:\t0x%X\n", info->base_addr);
0062     snd_iprintf(buffer, "Max Size:\t%d\n", info->max_size);
0063     snd_iprintf(buffer, "Loader Date:\t%.8s\n", (char *)&info->bld_date);
0064     snd_iprintf(buffer, "Loader Time:\t%.8s\n", (char *)&info->bld_time);
0065 
0066 end:
0067     kfree(info);
0068 }
0069 
0070 static void
0071 proc_read_meters(struct snd_info_entry *entry,
0072          struct snd_info_buffer *buffer)
0073 {
0074     struct snd_bebob *bebob = entry->private_data;
0075     const struct snd_bebob_meter_spec *spec = bebob->spec->meter;
0076     u32 *buf;
0077     unsigned int i, c, channels, size;
0078 
0079     if (spec == NULL)
0080         return;
0081 
0082     channels = spec->num * 2;
0083     size = channels * sizeof(u32);
0084     buf = kmalloc(size, GFP_KERNEL);
0085     if (buf == NULL)
0086         return;
0087 
0088     if (spec->get(bebob, buf, size) < 0)
0089         goto end;
0090 
0091     for (i = 0, c = 1; i < channels; i++) {
0092         snd_iprintf(buffer, "%s %d:\t%d\n",
0093                 spec->labels[i / 2], c++, buf[i]);
0094         if ((i + 1 < channels - 1) &&
0095             (strcmp(spec->labels[i / 2],
0096                 spec->labels[(i + 1) / 2]) != 0))
0097             c = 1;
0098     }
0099 end:
0100     kfree(buf);
0101 }
0102 
0103 static void
0104 proc_read_formation(struct snd_info_entry *entry,
0105         struct snd_info_buffer *buffer)
0106 {
0107     struct snd_bebob *bebob = entry->private_data;
0108     struct snd_bebob_stream_formation *formation;
0109     unsigned int i;
0110 
0111     snd_iprintf(buffer, "Output Stream from device:\n");
0112     snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
0113     formation = bebob->tx_stream_formations;
0114     for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
0115         snd_iprintf(buffer,
0116                 "\t%d\t%d\t%d\n", snd_bebob_rate_table[i],
0117                 formation[i].pcm, formation[i].midi);
0118     }
0119 
0120     snd_iprintf(buffer, "Input Stream to device:\n");
0121     snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
0122     formation = bebob->rx_stream_formations;
0123     for (i = 0; i < SND_BEBOB_STRM_FMT_ENTRIES; i++) {
0124         snd_iprintf(buffer,
0125                 "\t%d\t%d\t%d\n", snd_bebob_rate_table[i],
0126                 formation[i].pcm, formation[i].midi);
0127     }
0128 }
0129 
0130 static void
0131 proc_read_clock(struct snd_info_entry *entry,
0132         struct snd_info_buffer *buffer)
0133 {
0134     static const char *const clk_labels[] = {
0135         "Internal",
0136         "External",
0137         "SYT-Match",
0138     };
0139     struct snd_bebob *bebob = entry->private_data;
0140     const struct snd_bebob_rate_spec *rate_spec = bebob->spec->rate;
0141     const struct snd_bebob_clock_spec *clk_spec = bebob->spec->clock;
0142     enum snd_bebob_clock_type src;
0143     unsigned int rate;
0144 
0145     if (rate_spec->get(bebob, &rate) >= 0)
0146         snd_iprintf(buffer, "Sampling rate: %d\n", rate);
0147 
0148     if (snd_bebob_stream_get_clock_src(bebob, &src) >= 0) {
0149         if (clk_spec)
0150             snd_iprintf(buffer, "Clock Source: %s\n",
0151                     clk_labels[src]);
0152         else
0153             snd_iprintf(buffer, "Clock Source: %s (MSU-dest: %d)\n",
0154                     clk_labels[src], bebob->sync_input_plug);
0155     }
0156 }
0157 
0158 static void
0159 add_node(struct snd_bebob *bebob, struct snd_info_entry *root, const char *name,
0160      void (*op)(struct snd_info_entry *e, struct snd_info_buffer *b))
0161 {
0162     struct snd_info_entry *entry;
0163 
0164     entry = snd_info_create_card_entry(bebob->card, name, root);
0165     if (entry)
0166         snd_info_set_text_ops(entry, bebob, op);
0167 }
0168 
0169 void snd_bebob_proc_init(struct snd_bebob *bebob)
0170 {
0171     struct snd_info_entry *root;
0172 
0173     /*
0174      * All nodes are automatically removed at snd_card_disconnect(),
0175      * by following to link list.
0176      */
0177     root = snd_info_create_card_entry(bebob->card, "firewire",
0178                       bebob->card->proc_root);
0179     if (root == NULL)
0180         return;
0181     root->mode = S_IFDIR | 0555;
0182 
0183     add_node(bebob, root, "clock", proc_read_clock);
0184     add_node(bebob, root, "firmware", proc_read_hw_info);
0185     add_node(bebob, root, "formation", proc_read_formation);
0186 
0187     if (bebob->spec->meter != NULL)
0188         add_node(bebob, root, "meter", proc_read_meters);
0189 }