162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * oxfw_proc.c - a part of driver for OXFW970/971 based devices
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2014 Takashi Sakamoto
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "./oxfw.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cistatic void proc_read_formation(struct snd_info_entry *entry,
1162306a36Sopenharmony_ci				struct snd_info_buffer *buffer)
1262306a36Sopenharmony_ci{
1362306a36Sopenharmony_ci	struct snd_oxfw *oxfw = entry->private_data;
1462306a36Sopenharmony_ci	struct snd_oxfw_stream_formation formation, curr;
1562306a36Sopenharmony_ci	u8 *format;
1662306a36Sopenharmony_ci	char flag;
1762306a36Sopenharmony_ci	int i, err;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	/* Show input. */
2062306a36Sopenharmony_ci	err = snd_oxfw_stream_get_current_formation(oxfw,
2162306a36Sopenharmony_ci						    AVC_GENERAL_PLUG_DIR_IN,
2262306a36Sopenharmony_ci						    &curr);
2362306a36Sopenharmony_ci	if (err < 0)
2462306a36Sopenharmony_ci		return;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	snd_iprintf(buffer, "Input Stream to device:\n");
2762306a36Sopenharmony_ci	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
2862306a36Sopenharmony_ci	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
2962306a36Sopenharmony_ci		format = oxfw->rx_stream_formats[i];
3062306a36Sopenharmony_ci		if (format == NULL)
3162306a36Sopenharmony_ci			continue;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci		err = snd_oxfw_stream_parse_format(format, &formation);
3462306a36Sopenharmony_ci		if (err < 0)
3562306a36Sopenharmony_ci			continue;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
3862306a36Sopenharmony_ci			flag = '*';
3962306a36Sopenharmony_ci		else
4062306a36Sopenharmony_ci			flag = ' ';
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
4362306a36Sopenharmony_ci			    formation.rate, formation.pcm, formation.midi);
4462306a36Sopenharmony_ci	}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	if (!oxfw->has_output)
4762306a36Sopenharmony_ci		return;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	/* Show output. */
5062306a36Sopenharmony_ci	err = snd_oxfw_stream_get_current_formation(oxfw,
5162306a36Sopenharmony_ci						    AVC_GENERAL_PLUG_DIR_OUT,
5262306a36Sopenharmony_ci						    &curr);
5362306a36Sopenharmony_ci	if (err < 0)
5462306a36Sopenharmony_ci		return;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	snd_iprintf(buffer, "Output Stream from device:\n");
5762306a36Sopenharmony_ci	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
5862306a36Sopenharmony_ci	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
5962306a36Sopenharmony_ci		format = oxfw->tx_stream_formats[i];
6062306a36Sopenharmony_ci		if (format == NULL)
6162306a36Sopenharmony_ci			continue;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		err = snd_oxfw_stream_parse_format(format, &formation);
6462306a36Sopenharmony_ci		if (err < 0)
6562306a36Sopenharmony_ci			continue;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
6862306a36Sopenharmony_ci			flag = '*';
6962306a36Sopenharmony_ci		else
7062306a36Sopenharmony_ci			flag = ' ';
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
7362306a36Sopenharmony_ci			    formation.rate, formation.pcm, formation.midi);
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic void add_node(struct snd_oxfw *oxfw, struct snd_info_entry *root,
7862306a36Sopenharmony_ci		     const char *name,
7962306a36Sopenharmony_ci		     void (*op)(struct snd_info_entry *e,
8062306a36Sopenharmony_ci				struct snd_info_buffer *b))
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	struct snd_info_entry *entry;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	entry = snd_info_create_card_entry(oxfw->card, name, root);
8562306a36Sopenharmony_ci	if (entry)
8662306a36Sopenharmony_ci		snd_info_set_text_ops(entry, oxfw, op);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_civoid snd_oxfw_proc_init(struct snd_oxfw *oxfw)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	struct snd_info_entry *root;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	/*
9462306a36Sopenharmony_ci	 * All nodes are automatically removed at snd_card_disconnect(),
9562306a36Sopenharmony_ci	 * by following to link list.
9662306a36Sopenharmony_ci	 */
9762306a36Sopenharmony_ci	root = snd_info_create_card_entry(oxfw->card, "firewire",
9862306a36Sopenharmony_ci					  oxfw->card->proc_root);
9962306a36Sopenharmony_ci	if (root == NULL)
10062306a36Sopenharmony_ci		return;
10162306a36Sopenharmony_ci	root->mode = S_IFDIR | 0555;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	add_node(oxfw, root, "formation", proc_read_formation);
10462306a36Sopenharmony_ci}
105