/*
 * rt_codec_ioctl.h  --  RT56XX ALSA SoC audio driver IO control
 *
 * Copyright 2012 Realtek Microelectronics
 * Author: Bard <bardliao@realtek.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#define DEBUG 1
#include <linux/spi/spi.h>
#include <sound/soc.h>
#include "rt_codec_ioctl.h"

static struct rt_codec_ops rt_codec_ioctl_ops;

#if defined(CONFIG_SND_HWDEP) || defined(CONFIG_SND_HWDEP_MODULE)
#define RT_CE_CODEC_HWDEP_NAME "rt_codec hwdep "
static int rt_codec_hwdep_open(struct snd_hwdep *hw, struct file *file)
{
	struct snd_soc_codec *codec = hw->private_data;
	dev_dbg(codec->dev, "%s()\n", __func__);
	return 0;
}

static int rt_codec_hwdep_release(struct snd_hwdep *hw, struct file *file)
{
	struct snd_soc_codec *codec = hw->private_data;
	dev_dbg(codec->dev, "%s()\n", __func__);
	return 0;
}

static int rt_codec_hwdep_ioctl_common(struct snd_hwdep *hw,
		struct file *file, unsigned int cmd, unsigned long arg)
{
	struct snd_soc_codec *codec = hw->private_data;
	struct rt_codec_cmd __user *_rt_codec = (struct rt_codec_cmd *)arg;
	struct rt_codec_cmd rt_codec;
	int *buf, *p;

	if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec))) {
		dev_err(codec->dev,"copy_from_user faild\n");
		return -EFAULT;
	}
	dev_dbg(codec->dev, "%s(): rt_codec.number=%d, cmd=%d\n",
			__func__, rt_codec.number, cmd);
	buf = kmalloc(sizeof(*buf) * rt_codec.number, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;
	if (copy_from_user(buf, rt_codec.buf, sizeof(*buf) * rt_codec.number)) {
		goto err;
	}

	switch (cmd) {
	case RT_READ_CODEC_REG_IOCTL:
		for (p = buf; p < buf + rt_codec.number / 2; p++) {
			*(p + rt_codec.number / 2) = snd_soc_read(codec, *p);
		}
		if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * rt_codec.number))
			goto err;
		break;		

	case RT_WRITE_CODEC_REG_IOCTL:
		for (p = buf; p < buf + rt_codec.number / 2; p++)
			snd_soc_write(codec, *p, *(p + rt_codec.number / 2));
		break;

	case RT_READ_CODEC_INDEX_IOCTL:
		if (NULL == rt_codec_ioctl_ops.index_read)
			goto err;

		for (p = buf; p < buf + rt_codec.number / 2; p++)
			*(p+rt_codec.number/2) = rt_codec_ioctl_ops.index_read(
							codec, *p);
		if (copy_to_user(rt_codec.buf, buf,
			sizeof(*buf) * rt_codec.number))
			goto err;
		break;

	case RT_WRITE_CODEC_INDEX_IOCTL:
		if (NULL == rt_codec_ioctl_ops.index_write)
			goto err;

		for (p = buf; p < buf + rt_codec.number / 2; p++)
		{
			dev_dbg(codec->dev, "%x , %x\n",
				*p,*(p+rt_codec.number/2));
			rt_codec_ioctl_ops.index_write(codec, *p,
				*(p+rt_codec.number/2));
		}
		break;		

	default:
		if (NULL == rt_codec_ioctl_ops.ioctl_common)
			goto err;

		rt_codec_ioctl_ops.ioctl_common(hw, file, cmd, arg);
		break;
	}

	kfree(buf);
	return 0;

err:
	kfree(buf);
	return -EFAULT;
}

static int rt_codec_codec_dump_reg(struct snd_hwdep *hw,
		struct file *file, unsigned long arg)
{
	struct snd_soc_codec *codec = hw->private_data;
	struct rt_codec_cmd __user *_rt_codec =(struct rt_codec_cmd *)arg;
	struct rt_codec_cmd rt_codec;
	int i, *buf, number = codec->driver->reg_cache_size;

	dev_dbg(codec->dev, "enter %s, number = %d\n", __func__, number);
	if (copy_from_user(&rt_codec, _rt_codec, sizeof(rt_codec)))
		return -EFAULT;
	
	buf = kmalloc(sizeof(*buf) * number, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	for (i = 0; i < number/2; i++) {
		buf[i] = i << 1;
		buf[i + number / 2] = codec->read(codec, buf[i]);
	}
	if (copy_to_user(rt_codec.buf, buf, sizeof(*buf) * i))
		goto err;
	rt_codec.number = number;
	if (copy_to_user(_rt_codec, &rt_codec, sizeof(rt_codec)))
		goto err;
	kfree(buf);
	return 0;

err:
	kfree(buf);
	return -EFAULT;
}

static int rt_codec_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
			unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case RT_READ_ALL_CODEC_REG_IOCTL:
		return rt_codec_codec_dump_reg(hw, file, arg);

	default:
		return rt_codec_hwdep_ioctl_common(hw, file, cmd, arg);
	}

	return 0;
}

int realtek_ce_init_hwdep(struct snd_soc_codec *codec)
{
	struct snd_hwdep *hw;
	struct snd_card *card = codec->card->snd_card;
	int err;

	dev_dbg(codec->dev, "enter %s\n", __func__);

	if ((err = snd_hwdep_new(card, RT_CE_CODEC_HWDEP_NAME, 0, &hw)) < 0)
		return err;
	
	strcpy(hw->name, RT_CE_CODEC_HWDEP_NAME);
	hw->private_data = codec;
	hw->ops.open = rt_codec_hwdep_open;
	hw->ops.release = rt_codec_hwdep_release;
	hw->ops.ioctl = rt_codec_hwdep_ioctl;

	return 0;
}
EXPORT_SYMBOL_GPL(realtek_ce_init_hwdep);
#endif

struct rt_codec_ops *rt_codec_get_ioctl_ops(void)
{
	return &rt_codec_ioctl_ops;
}
EXPORT_SYMBOL_GPL(rt_codec_get_ioctl_ops);
