/*
 *  max517.c - Support for Maxim MAX517, MAX518 and MAX519
 *
 *  Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/err.h>

#include "../iio.h"
#include "dac.h"

#include "max517.h"

#define MAX517_DRV_NAME	"max517"

/* Commands */
#define COMMAND_CHANNEL0	0x00
#define COMMAND_CHANNEL1	0x01 /* for MAX518 and MAX519 */
#define COMMAND_PD		0x08 /* Power Down */

enum max517_device_ids {
	ID_MAX517,
	ID_MAX518,
	ID_MAX519,
};

struct max517_data {
	struct iio_dev		*indio_dev;
	struct i2c_client	*client;
	unsigned short		vref_mv[2];
};

/*
 * channel: bit 0: channel 1
 *          bit 1: channel 2
 * (this way, it's possible to set both channels at once)
 */
static ssize_t max517_set_value(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t count, int channel)
{
	struct iio_dev *dev_info = dev_get_drvdata(dev);
	struct max517_data *data = iio_priv(dev_info);
	struct i2c_client *client = data->client;
	u8 outbuf[4]; /* 1x or 2x command + value */
	int outbuf_size = 0;
	int res;
	long val;

	res = strict_strtol(buf, 10, &val);

	if (res)
		return res;

	if (val < 0 || val > 255)
		return -EINVAL;

	if (channel & 1) {
		outbuf[outbuf_size++] = COMMAND_CHANNEL0;
		outbuf[outbuf_size++] = val;
	}
	if (channel & 2) {
		outbuf[outbuf_size++] = COMMAND_CHANNEL1;
		outbuf[outbuf_size++] = val;
	}

	/*
	 * At this point, there are always 1 or 2 two-byte commands in
	 * outbuf. With 2 commands, the device can set two outputs
	 * simultaneously, latching the values upon the end of the I2C
	 * transfer.
	 */

	res = i2c_master_send(client, outbuf, outbuf_size);
	if (res < 0)
		return res;

	return count;
}

static ssize_t max517_set_value_1(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
	return max517_set_value(dev, attr, buf, count, 1);
}
static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0);

static ssize_t max517_set_value_2(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
	return max517_set_value(dev, attr, buf, count, 2);
}
static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1);

static ssize_t max517_set_value_both(struct device *dev,
				 struct device_attribute *attr,
				 const char *buf, size_t count)
{
	return max517_set_value(dev, attr, buf, count, 3);
}
static IIO_DEVICE_ATTR_NAMED(out1and2_raw, out1&2_raw, S_IWUSR, NULL,
		max517_set_value_both, -1);

static ssize_t max517_show_scale(struct device *dev,
				struct device_attribute *attr,
				char *buf, int channel)
{
	struct iio_dev *dev_info = dev_get_drvdata(dev);
	struct max517_data *data = iio_priv(dev_info);
	/* Corresponds to Vref / 2^(bits) */
	unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;

	return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
}

static ssize_t max517_show_scale1(struct device *dev,
				struct device_attribute *attr,
				char *buf)
{
	return max517_show_scale(dev, attr, buf, 1);
}
static IIO_DEVICE_ATTR(out1_scale, S_IRUGO, max517_show_scale1, NULL, 0);

static ssize_t max517_show_scale2(struct device *dev,
				struct device_attribute *attr,
				char *buf)
{
	return max517_show_scale(dev, attr, buf, 2);
}
static IIO_DEVICE_ATTR(out2_scale, S_IRUGO, max517_show_scale2, NULL, 0);

/* On MAX517 variant, we have one output */
static struct attribute *max517_attributes[] = {
	&iio_dev_attr_out1_raw.dev_attr.attr,
	&iio_dev_attr_out1_scale.dev_attr.attr,
	NULL
};

static struct attribute_group max517_attribute_group = {
	.attrs = max517_attributes,
};

/* On MAX518 and MAX519 variant, we have two outputs */
static struct attribute *max518_attributes[] = {
	&iio_dev_attr_out1_raw.dev_attr.attr,
	&iio_dev_attr_out1_scale.dev_attr.attr,
	&iio_dev_attr_out2_raw.dev_attr.attr,
	&iio_dev_attr_out2_scale.dev_attr.attr,
	&iio_dev_attr_out1and2_raw.dev_attr.attr,
	NULL
};

static struct attribute_group max518_attribute_group = {
	.attrs = max518_attributes,
};

static int max517_suspend(struct i2c_client *client, pm_message_t mesg)
{
	u8 outbuf = COMMAND_PD;

	return i2c_master_send(client, &outbuf, 1);
}

static int max517_resume(struct i2c_client *client)
{
	u8 outbuf = 0;

	return i2c_master_send(client, &outbuf, 1);
}

static const struct iio_info max517_info = {
	.attrs = &max517_attribute_group,
	.driver_module = THIS_MODULE,
};

static const struct iio_info max518_info = {
	.attrs = &max518_attribute_group,
	.driver_module = THIS_MODULE,
};

static int max517_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct max517_data *data;
	struct iio_dev *indio_dev;
	struct max517_platform_data *platform_data = client->dev.platform_data;
	int err;

	indio_dev = iio_allocate_device(sizeof(*data));
	if (indio_dev == NULL) {
		err = -ENOMEM;
		goto exit;
	}
	data = iio_priv(indio_dev);
	i2c_set_clientdata(client, indio_dev);
	data->client = client;

	/* establish that the iio_dev is a child of the i2c device */
	indio_dev->dev.parent = &client->dev;

	/* reduced attribute set for MAX517 */
	if (id->driver_data == ID_MAX517)
		indio_dev->info = &max517_info;
	else
		indio_dev->info = &max518_info;
	indio_dev->modes = INDIO_DIRECT_MODE;

	/*
	 * Reference voltage on MAX518 and default is 5V, else take vref_mv
	 * from platform_data
	 */
	if (id->driver_data == ID_MAX518 || !platform_data) {
		data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */
	} else {
		data->vref_mv[0] = platform_data->vref_mv[0];
		data->vref_mv[1] = platform_data->vref_mv[1];
	}

	err = iio_device_register(indio_dev);
	if (err)
		goto exit_free_device;

	dev_info(&client->dev, "DAC registered\n");

	return 0;

exit_free_device:
	iio_free_device(indio_dev);
exit:
	return err;
}

static int max517_remove(struct i2c_client *client)
{
	iio_free_device(i2c_get_clientdata(client));

	return 0;
}

static const struct i2c_device_id max517_id[] = {
	{ "max517", ID_MAX517 },
	{ "max518", ID_MAX518 },
	{ "max519", ID_MAX519 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, max517_id);

static struct i2c_driver max517_driver = {
	.driver = {
		.name	= MAX517_DRV_NAME,
	},
	.probe		= max517_probe,
	.remove		= max517_remove,
	.suspend	= max517_suspend,
	.resume		= max517_resume,
	.id_table	= max517_id,
};

static int __init max517_init(void)
{
	return i2c_add_driver(&max517_driver);
}

static void __exit max517_exit(void)
{
	i2c_del_driver(&max517_driver);
}

MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC");
MODULE_LICENSE("GPL");

module_init(max517_init);
module_exit(max517_exit);
