/*
 * mix.c
 *
 * Copyright (c) 2015 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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.
 */
#include "rsnd.h"

#define MIX_NAME_SIZE	16
#define MIX_NAME "mix"

struct rsnd_mix {
	struct rsnd_mix_platform_info *info; /* rcar_snd.h */
	struct rsnd_mod mod;
};

#define rsnd_mix_nr(priv) ((priv)->mix_nr)
#define for_each_rsnd_mix(pos, priv, i)					\
	for ((i) = 0;							\
	     ((i) < rsnd_mix_nr(priv)) &&				\
		     ((pos) = (struct rsnd_mix *)(priv)->mix + i);	\
	     i++)


static void rsnd_mix_soft_reset(struct rsnd_mod *mod)
{
	rsnd_mod_write(mod, MIX_SWRSR, 0);
	rsnd_mod_write(mod, MIX_SWRSR, 1);
}

#define rsnd_mix_initialize_lock(mod)	__rsnd_mix_initialize_lock(mod, 1)
#define rsnd_mix_initialize_unlock(mod)	__rsnd_mix_initialize_lock(mod, 0)
static void __rsnd_mix_initialize_lock(struct rsnd_mod *mod, u32 enable)
{
	rsnd_mod_write(mod, MIX_MIXIR, enable);
}

static void rsnd_mix_volume_update(struct rsnd_dai_stream *io,
				  struct rsnd_mod *mod)
{

	/* Disable MIX dB setting */
	rsnd_mod_write(mod, MIX_MDBER, 0);

	rsnd_mod_write(mod, MIX_MDBAR, 0);
	rsnd_mod_write(mod, MIX_MDBBR, 0);
	rsnd_mod_write(mod, MIX_MDBCR, 0);
	rsnd_mod_write(mod, MIX_MDBDR, 0);

	/* Enable MIX dB setting */
	rsnd_mod_write(mod, MIX_MDBER, 1);
}

static int rsnd_mix_init(struct rsnd_mod *mod,
			 struct rsnd_dai_stream *io,
			 struct rsnd_priv *priv)
{
	rsnd_mod_power_on(mod);

	rsnd_mix_soft_reset(mod);

	rsnd_mix_initialize_lock(mod);

	rsnd_mod_write(mod, MIX_ADINR, rsnd_get_adinr_chan(mod, io));

	rsnd_path_parse(priv, io);

	/* volume step */
	rsnd_mod_write(mod, MIX_MIXMR, 0);
	rsnd_mod_write(mod, MIX_MVPDR, 0);

	rsnd_mix_volume_update(io, mod);

	rsnd_mix_initialize_unlock(mod);

	return 0;
}

static int rsnd_mix_quit(struct rsnd_mod *mod,
			 struct rsnd_dai_stream *io,
			 struct rsnd_priv *priv)
{
	rsnd_mod_power_off(mod);

	return 0;
}

static struct rsnd_mod_ops rsnd_mix_ops = {
	.name		= MIX_NAME,
	.init		= rsnd_mix_init,
	.quit		= rsnd_mix_quit,
};

struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id)
{
	if (WARN_ON(id < 0 || id >= rsnd_mix_nr(priv)))
		id = 0;

	return rsnd_mod_get((struct rsnd_mix *)(priv->mix) + id);
}

static void rsnd_of_parse_mix(struct platform_device *pdev,
			      const struct rsnd_of_data *of_data,
			      struct rsnd_priv *priv)
{
	struct device_node *node;
	struct rsnd_mix_platform_info *mix_info;
	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
	struct device *dev = &pdev->dev;
	int nr;

	if (!of_data)
		return;

	node = of_get_child_by_name(dev->of_node, "rcar_sound,mix");
	if (!node)
		return;

	nr = of_get_child_count(node);
	if (!nr)
		goto rsnd_of_parse_mix_end;

	mix_info = devm_kzalloc(dev,
				sizeof(struct rsnd_mix_platform_info) * nr,
				GFP_KERNEL);
	if (!mix_info) {
		dev_err(dev, "mix info allocation error\n");
		goto rsnd_of_parse_mix_end;
	}

	info->mix_info		= mix_info;
	info->mix_info_nr	= nr;

rsnd_of_parse_mix_end:
	of_node_put(node);

}

int rsnd_mix_probe(struct platform_device *pdev,
		   const struct rsnd_of_data *of_data,
		   struct rsnd_priv *priv)
{
	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_mix *mix;
	struct clk *clk;
	char name[MIX_NAME_SIZE];
	int i, nr, ret;

	/* This driver doesn't support Gen1 at this point */
	if (rsnd_is_gen1(priv))
		return 0;

	rsnd_of_parse_mix(pdev, of_data, priv);

	nr = info->mix_info_nr;
	if (!nr)
		return 0;

	mix	= devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
	if (!mix)
		return -ENOMEM;

	priv->mix_nr	= nr;
	priv->mix	= mix;

	for_each_rsnd_mix(mix, priv, i) {
		snprintf(name, MIX_NAME_SIZE, "%s.%d",
			 MIX_NAME, i);

		clk = devm_clk_get(dev, name);
		if (IS_ERR(clk))
			return PTR_ERR(clk);

		mix->info = &info->mix_info[i];

		ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
				    clk, RSND_MOD_MIX, i);
		if (ret)
			return ret;
	}

	return 0;
}

void rsnd_mix_remove(struct platform_device *pdev,
		     struct rsnd_priv *priv)
{
	struct rsnd_mix *mix;
	int i;

	for_each_rsnd_mix(mix, priv, i) {
		rsnd_mod_quit(rsnd_mod_get(mix));
	}
}
