/*
 * Renesas R-Car Gen1 SRU/SSI support
 *
 * Copyright (C) 2013 Renesas Solutions Corp.
 * 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"

struct rsnd_gen {
	void __iomem *base[RSND_BASE_MAX];

	struct rsnd_gen_ops *ops;

	struct regmap *regmap;
	struct regmap_field *regs[RSND_REG_MAX];
};

#define rsnd_priv_to_gen(p)	((struct rsnd_gen *)(p)->gen)

#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size)	\
	[id] = {							\
		.reg = (unsigned int)gen->base[reg_id] + offset,	\
		.lsb = 0,						\
		.msb = 31,						\
		.id_size = _id_size,					\
		.id_offset = _id_offset,				\
	}

/*
 *		basic function
 */
static int rsnd_regmap_write32(void *context, const void *_data, size_t count)
{
	struct rsnd_priv *priv = context;
	struct device *dev = rsnd_priv_to_dev(priv);
	u32 *data = (u32 *)_data;
	u32 val = data[1];
	void __iomem *reg = (void *)data[0];

	iowrite32(val, reg);

	dev_dbg(dev, "w %p : %08x\n", reg, val);

	return 0;
}

static int rsnd_regmap_read32(void *context,
			      const void *_data, size_t reg_size,
			      void *_val, size_t val_size)
{
	struct rsnd_priv *priv = context;
	struct device *dev = rsnd_priv_to_dev(priv);
	u32 *data = (u32 *)_data;
	u32 *val = (u32 *)_val;
	void __iomem *reg = (void *)data[0];

	*val = ioread32(reg);

	dev_dbg(dev, "r %p : %08x\n", reg, *val);

	return 0;
}

static struct regmap_bus rsnd_regmap_bus = {
	.write				= rsnd_regmap_write32,
	.read				= rsnd_regmap_read32,
	.reg_format_endian_default	= REGMAP_ENDIAN_NATIVE,
	.val_format_endian_default	= REGMAP_ENDIAN_NATIVE,
};

static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
				  struct rsnd_gen *gen, enum rsnd_reg reg)
{
	if (!gen->regs[reg]) {
		struct device *dev = rsnd_priv_to_dev(priv);

		dev_err(dev, "unsupported register access %x\n", reg);
		return 0;
	}

	return 1;
}

u32 rsnd_read(struct rsnd_priv *priv,
	      struct rsnd_mod *mod, enum rsnd_reg reg)
{
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
	u32 val;

	if (!rsnd_is_accessible_reg(priv, gen, reg))
		return 0;

	regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);

	return val;
}

void rsnd_write(struct rsnd_priv *priv,
		struct rsnd_mod *mod,
		enum rsnd_reg reg, u32 data)
{
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);

	if (!rsnd_is_accessible_reg(priv, gen, reg))
		return;

	regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
}

void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
	       enum rsnd_reg reg, u32 mask, u32 data)
{
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);

	if (!rsnd_is_accessible_reg(priv, gen, reg))
		return;

	regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
				  mask, data);
}

static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
				struct rsnd_gen  *gen,
				struct reg_field *regf)
{
	int i;
	struct device *dev = rsnd_priv_to_dev(priv);
	struct regmap_config regc;

	memset(&regc, 0, sizeof(regc));
	regc.reg_bits = 32;
	regc.val_bits = 32;

	gen->regmap = devm_regmap_init(dev, &rsnd_regmap_bus, priv, &regc);
	if (IS_ERR(gen->regmap)) {
		dev_err(dev, "regmap error %ld\n", PTR_ERR(gen->regmap));
		return PTR_ERR(gen->regmap);
	}

	for (i = 0; i < RSND_REG_MAX; i++) {
		gen->regs[i] = NULL;
		if (!regf[i].reg)
			continue;

		gen->regs[i] = devm_regmap_field_alloc(dev, gen->regmap, regf[i]);
		if (IS_ERR(gen->regs[i]))
			return PTR_ERR(gen->regs[i]);

	}

	return 0;
}

/*
 *	DMA read/write register offset
 *
 *	RSND_xxx_I_N	for Audio DMAC input
 *	RSND_xxx_O_N	for Audio DMAC output
 *	RSND_xxx_I_P	for Audio DMAC peri peri input
 *	RSND_xxx_O_P	for Audio DMAC peri peri output
 *
 *	ex) R-Car H2 case
 *	      mod        / DMAC in    / DMAC out   / DMAC PP in / DMAC pp out
 *	SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000
 *	SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
 *	CMD : 0xec500000 / 0xec008000                             0xec308000
 */
#define RDMA_SSI_I_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
#define RDMA_SSI_O_N(addr, i)	(addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)

#define RDMA_SSI_I_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSI_O_P(addr, i)	(addr ##_reg - 0x00141000 + (0x1000 * i))

#define RDMA_SRC_I_N(addr, i)	(addr ##_reg - 0x00500000 + (0x400 * i))
#define RDMA_SRC_O_N(addr, i)	(addr ##_reg - 0x004fc000 + (0x400 * i))

#define RDMA_SRC_I_P(addr, i)	(addr ##_reg - 0x00200000 + (0x400 * i))
#define RDMA_SRC_O_P(addr, i)	(addr ##_reg - 0x001fc000 + (0x400 * i))

#define RDMA_CMD_O_N(addr, i)	(addr ##_reg - 0x004f8000 + (0x400 * i))
#define RDMA_CMD_O_P(addr, i)	(addr ##_reg - 0x001f8000 + (0x400 * i))

void rsnd_gen_dma_addr(struct rsnd_priv *priv,
		       struct rsnd_dma *dma,
		       struct dma_slave_config *cfg,
		       int is_play, int slave_id)
{
	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
	dma_addr_t ssi_reg = platform_get_resource(pdev,
				IORESOURCE_MEM, RSND_GEN2_SSI)->start;
	dma_addr_t src_reg = platform_get_resource(pdev,
				IORESOURCE_MEM, RSND_GEN2_SCU)->start;
	int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod);
	int use_src = !!rsnd_io_to_mod_src(io);
	int use_dvc = !!rsnd_io_to_mod_dvc(io);
	int id = rsnd_mod_id(mod);
	struct dma_addr {
		dma_addr_t src_addr;
		dma_addr_t dst_addr;
	} dma_addrs[2][2][3] = {
		{ /* SRC */
			/* Capture */
			{{ 0,				0 },
			 { RDMA_SRC_O_N(src, id),	0 },
			 { RDMA_CMD_O_N(src, id),	0 }},
			/* Playback */
			{{ 0,				0, },
			 { 0,				RDMA_SRC_I_N(src, id) },
			 { 0,				RDMA_SRC_I_N(src, id) }}
		}, { /* SSI */
			/* Capture */
			{{ RDMA_SSI_O_N(ssi, id),	0 },
			 { RDMA_SSI_O_P(ssi, id),	RDMA_SRC_I_P(src, id) },
			 { RDMA_SSI_O_P(ssi, id),	RDMA_SRC_I_P(src, id) }},
			/* Playback */
			{{ 0,				RDMA_SSI_I_N(ssi, id) },
			 { RDMA_SRC_O_P(src, id),	RDMA_SSI_I_P(ssi, id) },
			 { RDMA_CMD_O_P(src, id),	RDMA_SSI_I_P(ssi, id) }}
		}
	};

	cfg->slave_id	= slave_id;
	cfg->src_addr	= 0;
	cfg->dst_addr	= 0;
	cfg->direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;

	/*
	 * gen1 uses default DMA addr
	 */
	if (rsnd_is_gen1(priv))
		return;

	/* it shouldn't happen */
	if (use_dvc & !use_src) {
		dev_err(dev, "DVC is selected without SRC\n");
		return;
	}

	cfg->src_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].src_addr;
	cfg->dst_addr = dma_addrs[is_ssi][is_play][use_src + use_dvc].dst_addr;

	dev_dbg(dev, "dma%d addr - src : %x / dst : %x\n",
		id, cfg->src_addr, cfg->dst_addr);
}

/*
 *		Gen2
 */

/* single address mapping */
#define RSND_GEN2_S_REG(gen, reg, id, offset)				\
	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)

/* multi address mapping */
#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset)		\
	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)

static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
{
	struct reg_field regf[RSND_REG_MAX] = {
		RSND_GEN2_S_REG(gen, SSIU,	SSI_MODE0,	0x800),
		RSND_GEN2_S_REG(gen, SSIU,	SSI_MODE1,	0x804),
		/* FIXME: it needs SSI_MODE2/3 in the future */
		RSND_GEN2_M_REG(gen, SSIU,	SSI_BUSIF_MODE,	0x0,	0x80),
		RSND_GEN2_M_REG(gen, SSIU,	SSI_BUSIF_ADINR,0x4,	0x80),
		RSND_GEN2_M_REG(gen, SSIU,	SSI_CTRL,	0x10,	0x80),
		RSND_GEN2_M_REG(gen, SSIU,	INT_ENABLE,	0x18,	0x80),

		RSND_GEN2_M_REG(gen, SCU,	SRC_BUSIF_MODE,	0x0,	0x20),
		RSND_GEN2_M_REG(gen, SCU,	SRC_ROUTE_MODE0,0xc,	0x20),
		RSND_GEN2_M_REG(gen, SCU,	SRC_CTRL,	0x10,	0x20),
		RSND_GEN2_M_REG(gen, SCU,	CMD_ROUTE_SLCT,	0x18c,	0x20),
		RSND_GEN2_M_REG(gen, SCU,	CMD_CTRL,	0x190,	0x20),
		RSND_GEN2_M_REG(gen, SCU,	SRC_SWRSR,	0x200,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCIR,	0x204,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_ADINR,	0x214,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_IFSCR,	0x21c,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_IFSVR,	0x220,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_SRCCR,	0x224,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_BSDSR,	0x22c,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	SRC_BSISR,	0x238,	0x40),
		RSND_GEN2_M_REG(gen, SCU,	DVC_SWRSR,	0xe00,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUIR,	0xe04,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_ADINR,	0xe08,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUCR,	0xe10,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_ZCMCR,	0xe14,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL0R,	0xe28,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_VOL1R,	0xe2c,	0x100),
		RSND_GEN2_M_REG(gen, SCU,	DVC_DVUER,	0xe48,	0x100),

		RSND_GEN2_S_REG(gen, ADG,	BRRA,		0x00),
		RSND_GEN2_S_REG(gen, ADG,	BRRB,		0x04),
		RSND_GEN2_S_REG(gen, ADG,	SSICKR,		0x08),
		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL0,	0x0c),
		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL1,	0x10),
		RSND_GEN2_S_REG(gen, ADG,	AUDIO_CLK_SEL2,	0x14),
		RSND_GEN2_S_REG(gen, ADG,	DIV_EN,		0x30),
		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL0,	0x34),
		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL1,	0x38),
		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL2,	0x3c),
		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL3,	0x40),
		RSND_GEN2_S_REG(gen, ADG,	SRCIN_TIMSEL4,	0x44),
		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL0,	0x48),
		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL1,	0x4c),
		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL2,	0x50),
		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL3,	0x54),
		RSND_GEN2_S_REG(gen, ADG,	SRCOUT_TIMSEL4,	0x58),
		RSND_GEN2_S_REG(gen, ADG,	CMDOUT_TIMSEL,	0x5c),

		RSND_GEN2_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
		RSND_GEN2_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
		RSND_GEN2_M_REG(gen, SSI,	SSITDR,		0x08,	0x40),
		RSND_GEN2_M_REG(gen, SSI,	SSIRDR,		0x0c,	0x40),
		RSND_GEN2_M_REG(gen, SSI,	SSIWSR,		0x20,	0x40),
	};

	return rsnd_gen_regmap_init(priv, gen, regf);
}

static int rsnd_gen2_probe(struct platform_device *pdev,
			   struct rsnd_priv *priv)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
	struct resource *scu_res;
	struct resource *adg_res;
	struct resource *ssiu_res;
	struct resource *ssi_res;
	int ret;

	/*
	 * map address
	 */
	scu_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SCU);
	adg_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_ADG);
	ssiu_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSIU);
	ssi_res  = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN2_SSI);

	gen->base[RSND_GEN2_SCU]  = devm_ioremap_resource(dev, scu_res);
	gen->base[RSND_GEN2_ADG]  = devm_ioremap_resource(dev, adg_res);
	gen->base[RSND_GEN2_SSIU] = devm_ioremap_resource(dev, ssiu_res);
	gen->base[RSND_GEN2_SSI]  = devm_ioremap_resource(dev, ssi_res);
	if (IS_ERR(gen->base[RSND_GEN2_SCU])  ||
	    IS_ERR(gen->base[RSND_GEN2_ADG])  ||
	    IS_ERR(gen->base[RSND_GEN2_SSIU]) ||
	    IS_ERR(gen->base[RSND_GEN2_SSI]))
		return -ENODEV;

	ret = rsnd_gen2_regmap_init(priv, gen);
	if (ret < 0)
		return ret;

	dev_dbg(dev, "Gen2 device probed\n");
	dev_dbg(dev, "SCU  : %pap => %p\n", &scu_res->start,
		gen->base[RSND_GEN2_SCU]);
	dev_dbg(dev, "ADG  : %pap => %p\n", &adg_res->start,
		gen->base[RSND_GEN2_ADG]);
	dev_dbg(dev, "SSIU : %pap => %p\n", &ssiu_res->start,
		gen->base[RSND_GEN2_SSIU]);
	dev_dbg(dev, "SSI  : %pap => %p\n", &ssi_res->start,
		gen->base[RSND_GEN2_SSI]);

	return 0;
}

/*
 *		Gen1
 */

/* single address mapping */
#define RSND_GEN1_S_REG(gen, reg, id, offset)	\
	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)

/* multi address mapping */
#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset)	\
	RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)

static int rsnd_gen1_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen)
{
	struct reg_field regf[RSND_REG_MAX] = {
		RSND_GEN1_S_REG(gen, SRU,	SRC_ROUTE_SEL,	0x00),
		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL0,	0x08),
		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL1,	0x0c),
		RSND_GEN1_S_REG(gen, SRU,	SRC_TMG_SEL2,	0x10),
		RSND_GEN1_S_REG(gen, SRU,	SRC_ROUTE_CTRL,	0xc0),
		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE0,	0xD0),
		RSND_GEN1_S_REG(gen, SRU,	SSI_MODE1,	0xD4),
		RSND_GEN1_M_REG(gen, SRU,	SRC_BUSIF_MODE,	0x20,	0x4),
		RSND_GEN1_M_REG(gen, SRU,	SRC_ROUTE_MODE0,0x50,	0x8),
		RSND_GEN1_M_REG(gen, SRU,	SRC_SWRSR,	0x200,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_SRCIR,	0x204,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_ADINR,	0x214,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_IFSCR,	0x21c,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_IFSVR,	0x220,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_SRCCR,	0x224,	0x40),
		RSND_GEN1_M_REG(gen, SRU,	SRC_MNFSR,	0x228,	0x40),

		RSND_GEN1_S_REG(gen, ADG,	BRRA,		0x00),
		RSND_GEN1_S_REG(gen, ADG,	BRRB,		0x04),
		RSND_GEN1_S_REG(gen, ADG,	SSICKR,		0x08),
		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL0,	0x0c),
		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL1,	0x10),
		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL3,	0x18),
		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL4,	0x1c),
		RSND_GEN1_S_REG(gen, ADG,	AUDIO_CLK_SEL5,	0x20),

		RSND_GEN1_M_REG(gen, SSI,	SSICR,		0x00,	0x40),
		RSND_GEN1_M_REG(gen, SSI,	SSISR,		0x04,	0x40),
		RSND_GEN1_M_REG(gen, SSI,	SSITDR,		0x08,	0x40),
		RSND_GEN1_M_REG(gen, SSI,	SSIRDR,		0x0c,	0x40),
		RSND_GEN1_M_REG(gen, SSI,	SSIWSR,		0x20,	0x40),
	};

	return rsnd_gen_regmap_init(priv, gen, regf);
}

static int rsnd_gen1_probe(struct platform_device *pdev,
			   struct rsnd_priv *priv)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_gen *gen = rsnd_priv_to_gen(priv);
	struct resource *sru_res;
	struct resource *adg_res;
	struct resource *ssi_res;
	int ret;

	/*
	 * map address
	 */
	sru_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SRU);
	adg_res = platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_ADG);
	ssi_res	= platform_get_resource(pdev, IORESOURCE_MEM, RSND_GEN1_SSI);

	gen->base[RSND_GEN1_SRU] = devm_ioremap_resource(dev, sru_res);
	gen->base[RSND_GEN1_ADG] = devm_ioremap_resource(dev, adg_res);
	gen->base[RSND_GEN1_SSI] = devm_ioremap_resource(dev, ssi_res);
	if (IS_ERR(gen->base[RSND_GEN1_SRU]) ||
	    IS_ERR(gen->base[RSND_GEN1_ADG]) ||
	    IS_ERR(gen->base[RSND_GEN1_SSI]))
		return -ENODEV;

	ret = rsnd_gen1_regmap_init(priv, gen);
	if (ret < 0)
		return ret;

	dev_dbg(dev, "Gen1 device probed\n");
	dev_dbg(dev, "SRU : %pap => %p\n",	&sru_res->start,
						gen->base[RSND_GEN1_SRU]);
	dev_dbg(dev, "ADG : %pap => %p\n",	&adg_res->start,
						gen->base[RSND_GEN1_ADG]);
	dev_dbg(dev, "SSI : %pap => %p\n",	&ssi_res->start,
						gen->base[RSND_GEN1_SSI]);

	return 0;

}

/*
 *		Gen
 */
static void rsnd_of_parse_gen(struct platform_device *pdev,
			      const struct rsnd_of_data *of_data,
			      struct rsnd_priv *priv)
{
	struct rcar_snd_info *info = priv->info;

	if (!of_data)
		return;

	info->flags = of_data->flags;
}

int rsnd_gen_probe(struct platform_device *pdev,
		   const struct rsnd_of_data *of_data,
		   struct rsnd_priv *priv)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_gen *gen;
	int ret;

	rsnd_of_parse_gen(pdev, of_data, priv);

	gen = devm_kzalloc(dev, sizeof(*gen), GFP_KERNEL);
	if (!gen) {
		dev_err(dev, "GEN allocate failed\n");
		return -ENOMEM;
	}

	priv->gen = gen;

	ret = -ENODEV;
	if (rsnd_is_gen1(priv))
		ret = rsnd_gen1_probe(pdev, priv);
	else if (rsnd_is_gen2(priv))
		ret = rsnd_gen2_probe(pdev, priv);

	if (ret < 0)
		dev_err(dev, "unknown generation R-Car sound device\n");

	return ret;
}
