/*
 *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
 *                   Creative Labs, Inc.
 *  Routines for control of EMU10K1 chips / proc interface routines
 *
 *  BUGS:
 *    --
 *
 *  TODO:
 *    --
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include "../../include/driver.h"
#include "../../include/emu10k1.h"

static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
					  snd_info_buffer_t * buffer,
					  char *title,
					  int status_reg,
					  int rate_reg)
{
	static char *clkaccy[4] = { "1000ppm", "50ppm", "variable", "unknown" };
	static int samplerate[16] = { 44100, 1, 2, 3, 48000, 5, 6, 7, 8, 9, 10, 11, 32000, 13, 14, 15 };
	static char *channel[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
	static char *emphasis[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" };
	unsigned int status, rate = 0;
	
	status = snd_emu10k1_ptr_read(emu, status_reg, 0);
	if (rate_reg > 0)
		rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);

	snd_iprintf(buffer, "\n%s\n", title);

	snd_iprintf(buffer, "Professional Mode     : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
	snd_iprintf(buffer, "Not Audio Data        : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
	snd_iprintf(buffer, "Copyright             : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
	snd_iprintf(buffer, "Emphasis              : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
	snd_iprintf(buffer, "Mode                  : %i\n", (status & SPCS_MODEMASK) >> 6);
	snd_iprintf(buffer, "Category Code         : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
	snd_iprintf(buffer, "Generation Status     : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
	snd_iprintf(buffer, "Source Mask           : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
	snd_iprintf(buffer, "Channel Number        : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
	snd_iprintf(buffer, "Sample Rate           : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
	snd_iprintf(buffer, "Clock Accuracy        : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);

	if (rate_reg > 0) {
		snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
		snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
		snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE);
	}
}

static void snd_emu10k1_proc_read(snd_info_buffer_t * buffer,
				  void *private_data)
{
	static char *outputs[32] = {
		/* 00 */ "Default C (left)",
		/* 01 */ "Default B (right)",
		/* 02 */ "???",
		/* 03 */ "???",
		/* 04 */ "???",
		/* 05 */ "???",
		/* 06 */ "???",
		/* 07 */ "???",
		/* 08 */ "???",
		/* 09 */ "???",
		/* 10 */ "???",
		/* 11 */ "???",
		/* 12 */ "Default A",
		/* 13 */ "Default D",
		/* 14 */ "???",
		/* 15 */ "???",
		/* 16 */ "???",
		/* 17 */ "???",
		/* 18 */ "ADC Left / CDROM S/PDIF Left",
		/* 19 */ "ADC Right / CDROM S/PDIF Right",
		/* 20 */ "MIC / Zoom Video Left",
		/* 21 */ "Zoom Video Right",
		/* 22 */ "S/PDIF Left",
		/* 23 */ "S/PDIF Right",
		/* 24 */ "???",
		/* 25 */ "???",
		/* 26 */ "???",
		/* 27 */ "???",
		/* 28 */ "???",
		/* 29 */ "???",
		/* 30 */ "???",
		/* 31 */ "???"
	};
	emu10k1_t *emu = snd_magic_cast(emu10k1_t, private_data, );
	unsigned int val;
	int idx;
	
	snd_iprintf(buffer, "EMU10K1\n\n");
	val = snd_emu10k1_ptr_read(emu, FXRT, 0);
	snd_iprintf(buffer, "Effect Send Routing   : A=%i, B=%i, C=%i, D=%i\n",
				(val & FXRT_CHANNELA) >> 16,
				(val & FXRT_CHANNELB) >> 20,
				(val & FXRT_CHANNELC) >> 24,
				(val & FXRT_CHANNELD) >> 28);
	snd_iprintf(buffer, "\nCaptured FX Outputs   :\n");
	for (idx = 0; idx < 32; idx++) {
		if (emu->efx_voices_mask & (1 << idx))
			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
	}
	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
	for (idx = 0; idx < 32; idx++)
		snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1);
	snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS);
	snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS);
	val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
	snd_iprintf(buffer, "\nZoomed Video\n");
	snd_iprintf(buffer, "Rate Locked           : %s\n", val & SRCS_RATELOCKED ? "on" : "off");
	snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE);
}

int snd_emu10k1_proc_init(emu10k1_t * emu)
{
	snd_info_entry_t *entry;
	
	if ((entry = snd_info_create_entry(emu->card, "emu10k1")) != NULL) {
		entry->private_data = emu;
		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
		entry->t.text.read_size = 4096;
		entry->t.text.read = snd_emu10k1_proc_read;
		if (snd_info_register(entry) < 0) {
			snd_info_free_entry(entry);
			entry = NULL;
		}
	}
	emu->proc_entry = entry;
	return 0;
}

int snd_emu10k1_proc_done(emu10k1_t * emu)
{
	if (emu->proc_entry) {
		snd_info_unregister(emu->proc_entry);
		emu->proc_entry = NULL;
	}
	return 0;
}
