// SPDX-License-Identifier: GPL-2.0-only
/*
 * TXx9 ACLC AC97 driver
 *
 * Copyright (C) 2009 Atsushi Nemoto
 *
 * Based on RBTX49xx patch from CELF patch archive.
 * (C) Copyright TOSHIBA CORPORATION 2004-2006
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/gfp.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include "txx9aclc.h"

#define AC97_DIR	\
	(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)

#define AC97_RATES	\
	SNDRV_PCM_RATE_8000_48000

#ifdef __BIG_ENDIAN
#define AC97_FMTS	SNDRV_PCM_FMTBIT_S16_BE
#else
#define AC97_FMTS	SNDRV_PCM_FMTBIT_S16_LE
#endif

static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);

/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;

static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
{
	return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
}

/* AC97 controller reads codec register */
static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
					 unsigned short reg)
{
	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
	void __iomem *base = drvdata->base;
	u32 dat;

	if (!(__raw_readl(base + ACINTSTS) & ACINT_CODECRDY(ac97->num)))
		return 0xffff;
	reg |= ac97->num << 7;
	dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
	__raw_writel(dat, base + ACREGACC);
	__raw_writel(ACINT_REGACCRDY, base + ACINTEN);
	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
		__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
		printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
		dat = 0xffff;
		goto done;
	}
	dat = __raw_readl(base + ACREGACC);
	if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
		printk(KERN_ERR "reg mismatch %x with %x\n",
			dat, reg);
		dat = 0xffff;
		goto done;
	}
	dat = (dat >> ACREGACC_DAT_SHIFT) & 0xffff;
done:
	__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
	return dat;
}

/* AC97 controller writes to codec register */
static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
				unsigned short val)
{
	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
	void __iomem *base = drvdata->base;

	__raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
		     (val << ACREGACC_DAT_SHIFT),
		     base + ACREGACC);
	__raw_writel(ACINT_REGACCRDY, base + ACINTEN);
	if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
		printk(KERN_ERR
			"ac97 write timeout (reg %#x)\n", reg);
	}
	__raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
}

static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
{
	struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
	void __iomem *base = drvdata->base;
	u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;

	__raw_writel(ACCTL_ENLINK, base + ACCTLDIS);
	udelay(1);
	__raw_writel(ACCTL_ENLINK, base + ACCTLEN);
	/* wait for primary codec ready status */
	__raw_writel(ready, base + ACINTEN);
	if (!wait_event_timeout(ac97_waitq,
				(__raw_readl(base + ACINTSTS) & ready) == ready,
				HZ)) {
		dev_err(&ac97->dev, "primary codec is not ready "
			"(status %#x)\n",
			__raw_readl(base + ACINTSTS));
	}
	__raw_writel(ACINT_REGACCRDY, base + ACINTSTS);
	__raw_writel(ready, base + ACINTDIS);
}

/* AC97 controller operations */
static struct snd_ac97_bus_ops txx9aclc_ac97_ops = {
	.read		= txx9aclc_ac97_read,
	.write		= txx9aclc_ac97_write,
	.reset		= txx9aclc_ac97_cold_reset,
};

static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
{
	struct txx9aclc_plat_drvdata *drvdata = dev_id;
	void __iomem *base = drvdata->base;

	__raw_writel(__raw_readl(base + ACINTMSTS), base + ACINTDIS);
	wake_up(&ac97_waitq);
	return IRQ_HANDLED;
}

static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
{
	txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
	return 0;
}

static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
{
	struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);

	/* disable AC-link */
	__raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
	txx9aclc_drvdata = NULL;
	return 0;
}

static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
	.bus_control		= true,
	.probe			= txx9aclc_ac97_probe,
	.remove			= txx9aclc_ac97_remove,
	.playback = {
		.rates		= AC97_RATES,
		.formats	= AC97_FMTS,
		.channels_min	= 2,
		.channels_max	= 2,
	},
	.capture = {
		.rates		= AC97_RATES,
		.formats	= AC97_FMTS,
		.channels_min	= 2,
		.channels_max	= 2,
	},
};

static const struct snd_soc_component_driver txx9aclc_ac97_component = {
	.name		= "txx9aclc-ac97",
};

static int txx9aclc_ac97_dev_probe(struct platform_device *pdev)
{
	struct txx9aclc_plat_drvdata *drvdata;
	struct resource *r;
	int err;
	int irq;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
		return -ENOMEM;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	drvdata->base = devm_ioremap_resource(&pdev->dev, r);
	if (IS_ERR(drvdata->base))
		return PTR_ERR(drvdata->base);

	platform_set_drvdata(pdev, drvdata);
	drvdata->physbase = r->start;
	if (sizeof(drvdata->physbase) > sizeof(r->start) &&
	    r->start >= TXX9_DIRECTMAP_BASE &&
	    r->start < TXX9_DIRECTMAP_BASE + 0x400000)
		drvdata->physbase |= 0xf00000000ull;
	err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
			       0, dev_name(&pdev->dev), drvdata);
	if (err < 0)
		return err;

	err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops);
	if (err < 0)
		return err;

	return devm_snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component,
					  &txx9aclc_ac97_dai, 1);
}

static int txx9aclc_ac97_dev_remove(struct platform_device *pdev)
{
	snd_soc_set_ac97_ops(NULL);
	return 0;
}

static struct platform_driver txx9aclc_ac97_driver = {
	.probe		= txx9aclc_ac97_dev_probe,
	.remove		= txx9aclc_ac97_dev_remove,
	.driver		= {
		.name	= "txx9aclc-ac97",
	},
};

module_platform_driver(txx9aclc_ac97_driver);

MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:txx9aclc-ac97");
