/*
 *   ALSA Driver for the PT2258 volume controller.
 *
 *	Copyright (c) 2006  Jochen Voss <voss@seehuhn.de>
 *
 *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */      

#include <sound/driver.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include <sound/i2c.h>
#include <sound/pt2258.h>

MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
MODULE_LICENSE("GPL");

#define PT2258_CMD_RESET 0xc0
#define PT2258_CMD_UNMUTE 0xf8
#define PT2258_CMD_MUTE 0xf9

static const unsigned char pt2258_channel_code[12] = {
	0x80, 0x90,		/* channel 1: -10dB, -1dB */
	0x40, 0x50,		/* channel 2: -10dB, -1dB */
	0x00, 0x10,		/* channel 3: -10dB, -1dB */
	0x20, 0x30,		/* channel 4: -10dB, -1dB */
	0x60, 0x70,		/* channel 5: -10dB, -1dB */
	0xa0, 0xb0		/* channel 6: -10dB, -1dB */
};

int snd_pt2258_reset(struct snd_pt2258 *pt)
{
	unsigned char bytes[2];
	int i;

	/* reset chip */
	bytes[0] = PT2258_CMD_RESET;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	/* mute all channels */
	pt->mute = 1;
	bytes[0] = PT2258_CMD_MUTE;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	/* set all channels to 0dB */
	for (i = 0; i < 6; ++i)
		pt->volume[i] = 0;
	bytes[0] = 0xd0;
	bytes[1] = 0xe0;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	return 0;

      __error:
	snd_i2c_unlock(pt->i2c_bus);
	snd_printk(KERN_ERR "PT2258 reset failed\n");
	return -EIO;
}

static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 79;
	return 0;
}

static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pt2258 *pt = kcontrol->private_data;
	int base = kcontrol->private_value;

	/* chip does not support register reads */
	ucontrol->value.integer.value[0] = 79 - pt->volume[base];
	ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1];
	return 0;
}

static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pt2258 *pt = kcontrol->private_data;
	int base = kcontrol->private_value;
	unsigned char bytes[2];
	int val0, val1;

	val0 = 79 - ucontrol->value.integer.value[0];
	val1 = 79 - ucontrol->value.integer.value[1];
	if (val0 == pt->volume[base] && val1 == pt->volume[base + 1])
		return 0;

	pt->volume[base] = val0;
	bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10);
	bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10);
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	pt->volume[base + 1] = val1;
	bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10);
	bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10);
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	return 1;

      __error:
	snd_i2c_unlock(pt->i2c_bus);
	snd_printk(KERN_ERR "PT2258 access failed\n");
	return -EIO;
}

#define pt2258_switch_info	snd_ctl_boolean_mono_info

static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pt2258 *pt = kcontrol->private_data;

	ucontrol->value.integer.value[0] = !pt->mute;
	return 0;
}

static int pt2258_switch_put(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pt2258 *pt = kcontrol->private_data;
	unsigned char bytes[2];
	int val;

	val = !ucontrol->value.integer.value[0];
	if (pt->mute == val)
		return 0;

	pt->mute = val;
	bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	return 1;

      __error:
	snd_i2c_unlock(pt->i2c_bus);
	snd_printk(KERN_ERR "PT2258 access failed 2\n");
	return -EIO;
}

static const DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0);

int snd_pt2258_build_controls(struct snd_pt2258 *pt)
{
	struct snd_kcontrol_new knew;
	char *names[3] = {
		"Mic Loopback Playback Volume",
		"Line Loopback Playback Volume",
		"CD Loopback Playback Volume"
	};
	int i, err;

	for (i = 0; i < 3; ++i) {
		memset(&knew, 0, sizeof(knew));
		knew.name = names[i];
		knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
		knew.count = 1;
		knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
		    SNDRV_CTL_ELEM_ACCESS_TLV_READ;
		knew.private_value = 2 * i;
		knew.info = pt2258_stereo_volume_info;
		knew.get = pt2258_stereo_volume_get;
		knew.put = pt2258_stereo_volume_put;
		knew.tlv.p = pt2258_db_scale;

		err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
		if (err < 0)
			return err;
	}

	memset(&knew, 0, sizeof(knew));
	knew.name = "Loopback Switch";
	knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
	knew.info = pt2258_switch_info;
	knew.get = pt2258_switch_get;
	knew.put = pt2258_switch_put;
	knew.access = 0;
	err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
	if (err < 0)
		return err;

	return 0;
}

EXPORT_SYMBOL(snd_pt2258_reset);
EXPORT_SYMBOL(snd_pt2258_build_controls);
