2 * fireworks_proc.c - a part of driver for Fireworks based devices
4 * Copyright (c) 2009-2010 Clemens Ladisch
5 * Copyright (c) 2013-2014 Takashi Sakamoto
7 * Licensed under the terms of the GNU General Public License, version 2.
10 #include "./fireworks.h"
12 static inline const char*
13 get_phys_name(struct snd_efw_phys_grp
*grp
, bool input
)
15 const char *const ch_type
[] = {
16 "Analog", "S/PDIF", "ADAT", "S/PDIF or ADAT", "Mirroring",
17 "Headphones", "I2S", "Guitar", "Pirzo Guitar", "Guitar String",
20 if (grp
->type
< ARRAY_SIZE(ch_type
))
21 return ch_type
[grp
->type
];
29 proc_read_hwinfo(struct snd_info_entry
*entry
, struct snd_info_buffer
*buffer
)
31 struct snd_efw
*efw
= entry
->private_data
;
33 struct snd_efw_hwinfo
*hwinfo
;
35 hwinfo
= kmalloc(sizeof(struct snd_efw_hwinfo
), GFP_KERNEL
);
39 if (snd_efw_command_get_hwinfo(efw
, hwinfo
) < 0)
42 snd_iprintf(buffer
, "guid_hi: 0x%X\n", hwinfo
->guid_hi
);
43 snd_iprintf(buffer
, "guid_lo: 0x%X\n", hwinfo
->guid_lo
);
44 snd_iprintf(buffer
, "type: 0x%X\n", hwinfo
->type
);
45 snd_iprintf(buffer
, "version: 0x%X\n", hwinfo
->version
);
46 snd_iprintf(buffer
, "vendor_name: %s\n", hwinfo
->vendor_name
);
47 snd_iprintf(buffer
, "model_name: %s\n", hwinfo
->model_name
);
49 snd_iprintf(buffer
, "dsp_version: 0x%X\n", hwinfo
->dsp_version
);
50 snd_iprintf(buffer
, "arm_version: 0x%X\n", hwinfo
->arm_version
);
51 snd_iprintf(buffer
, "fpga_version: 0x%X\n", hwinfo
->fpga_version
);
53 snd_iprintf(buffer
, "flags: 0x%X\n", hwinfo
->flags
);
55 snd_iprintf(buffer
, "max_sample_rate: 0x%X\n", hwinfo
->max_sample_rate
);
56 snd_iprintf(buffer
, "min_sample_rate: 0x%X\n", hwinfo
->min_sample_rate
);
57 snd_iprintf(buffer
, "supported_clock: 0x%X\n",
58 hwinfo
->supported_clocks
);
60 snd_iprintf(buffer
, "phys out: 0x%X\n", hwinfo
->phys_out
);
61 snd_iprintf(buffer
, "phys in: 0x%X\n", hwinfo
->phys_in
);
63 snd_iprintf(buffer
, "phys in grps: 0x%X\n",
64 hwinfo
->phys_in_grp_count
);
65 for (i
= 0; i
< hwinfo
->phys_in_grp_count
; i
++) {
67 "phys in grp[0x%d]: type 0x%d, count 0x%x\n",
68 i
, hwinfo
->phys_out_grps
[i
].type
,
69 hwinfo
->phys_out_grps
[i
].count
);
72 snd_iprintf(buffer
, "phys out grps: 0x%X\n",
73 hwinfo
->phys_out_grp_count
);
74 for (i
= 0; i
< hwinfo
->phys_out_grp_count
; i
++) {
76 "phys out grps[0x%d]: type 0x%d, count 0x%x\n",
77 i
, hwinfo
->phys_out_grps
[i
].type
,
78 hwinfo
->phys_out_grps
[i
].count
);
81 snd_iprintf(buffer
, "amdtp rx pcm channels 1x: 0x%X\n",
82 hwinfo
->amdtp_rx_pcm_channels
);
83 snd_iprintf(buffer
, "amdtp tx pcm channels 1x: 0x%X\n",
84 hwinfo
->amdtp_tx_pcm_channels
);
85 snd_iprintf(buffer
, "amdtp rx pcm channels 2x: 0x%X\n",
86 hwinfo
->amdtp_rx_pcm_channels_2x
);
87 snd_iprintf(buffer
, "amdtp tx pcm channels 2x: 0x%X\n",
88 hwinfo
->amdtp_tx_pcm_channels_2x
);
89 snd_iprintf(buffer
, "amdtp rx pcm channels 4x: 0x%X\n",
90 hwinfo
->amdtp_rx_pcm_channels_4x
);
91 snd_iprintf(buffer
, "amdtp tx pcm channels 4x: 0x%X\n",
92 hwinfo
->amdtp_tx_pcm_channels_4x
);
94 snd_iprintf(buffer
, "midi out ports: 0x%X\n", hwinfo
->midi_out_ports
);
95 snd_iprintf(buffer
, "midi in ports: 0x%X\n", hwinfo
->midi_in_ports
);
97 snd_iprintf(buffer
, "mixer playback channels: 0x%X\n",
98 hwinfo
->mixer_playback_channels
);
99 snd_iprintf(buffer
, "mixer capture channels: 0x%X\n",
100 hwinfo
->mixer_capture_channels
);
106 proc_read_clock(struct snd_info_entry
*entry
, struct snd_info_buffer
*buffer
)
108 struct snd_efw
*efw
= entry
->private_data
;
109 enum snd_efw_clock_source clock_source
;
110 unsigned int sampling_rate
;
112 if (snd_efw_command_get_clock_source(efw
, &clock_source
) < 0)
115 if (snd_efw_command_get_sampling_rate(efw
, &sampling_rate
) < 0)
118 snd_iprintf(buffer
, "Clock Source: %d\n", clock_source
);
119 snd_iprintf(buffer
, "Sampling Rate: %d\n", sampling_rate
);
124 * dB = 20 * log10(linear / 0x01000000)
125 * -144.0 dB when linear is 0
128 proc_read_phys_meters(struct snd_info_entry
*entry
,
129 struct snd_info_buffer
*buffer
)
131 struct snd_efw
*efw
= entry
->private_data
;
132 struct snd_efw_phys_meters
*meters
;
133 unsigned int g
, c
, m
, max
, size
;
138 size
= sizeof(struct snd_efw_phys_meters
) +
139 (efw
->phys_in
+ efw
->phys_out
) * sizeof(u32
);
140 meters
= kzalloc(size
, GFP_KERNEL
);
144 err
= snd_efw_command_get_phys_meters(efw
, meters
, size
);
148 snd_iprintf(buffer
, "Physical Meters:\n");
151 max
= min(efw
->phys_out
, meters
->out_meters
);
152 linear
= meters
->values
;
153 snd_iprintf(buffer
, " %d Outputs:\n", max
);
154 for (g
= 0; g
< efw
->phys_out_grp_count
; g
++) {
155 name
= get_phys_name(&efw
->phys_out_grps
[g
], false);
156 for (c
= 0; c
< efw
->phys_out_grps
[g
].count
; c
++) {
158 snd_iprintf(buffer
, "\t%s [%d]: %d\n",
159 name
, c
, linear
[m
++]);
164 max
= min(efw
->phys_in
, meters
->in_meters
);
165 linear
= meters
->values
+ meters
->out_meters
;
166 snd_iprintf(buffer
, " %d Inputs:\n", max
);
167 for (g
= 0; g
< efw
->phys_in_grp_count
; g
++) {
168 name
= get_phys_name(&efw
->phys_in_grps
[g
], true);
169 for (c
= 0; c
< efw
->phys_in_grps
[g
].count
; c
++)
171 snd_iprintf(buffer
, "\t%s [%d]: %d\n",
172 name
, c
, linear
[m
++]);
179 proc_read_queues_state(struct snd_info_entry
*entry
,
180 struct snd_info_buffer
*buffer
)
182 struct snd_efw
*efw
= entry
->private_data
;
183 unsigned int consumed
;
185 if (efw
->pull_ptr
> efw
->push_ptr
)
186 consumed
= snd_efw_resp_buf_size
-
187 (unsigned int)(efw
->pull_ptr
- efw
->push_ptr
);
189 consumed
= (unsigned int)(efw
->push_ptr
- efw
->pull_ptr
);
191 snd_iprintf(buffer
, "%d %d/%d\n",
192 efw
->resp_queues
, consumed
, snd_efw_resp_buf_size
);
196 add_node(struct snd_efw
*efw
, struct snd_info_entry
*root
, const char *name
,
197 void (*op
)(struct snd_info_entry
*e
, struct snd_info_buffer
*b
))
199 struct snd_info_entry
*entry
;
201 entry
= snd_info_create_card_entry(efw
->card
, name
, root
);
205 snd_info_set_text_ops(entry
, efw
, op
);
206 if (snd_info_register(entry
) < 0)
207 snd_info_free_entry(entry
);
210 void snd_efw_proc_init(struct snd_efw
*efw
)
212 struct snd_info_entry
*root
;
215 * All nodes are automatically removed at snd_card_disconnect(),
216 * by following to link list.
218 root
= snd_info_create_card_entry(efw
->card
, "firewire",
219 efw
->card
->proc_root
);
222 root
->mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
223 if (snd_info_register(root
) < 0) {
224 snd_info_free_entry(root
);
228 add_node(efw
, root
, "clock", proc_read_clock
);
229 add_node(efw
, root
, "firmware", proc_read_hwinfo
);
230 add_node(efw
, root
, "meters", proc_read_phys_meters
);
231 add_node(efw
, root
, "queues", proc_read_queues_state
);