/*
 * Copyright 2017 NXP.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <sound/soc.h>

#include "fsl_sai.h"

struct imx_pdm_data {
	struct snd_soc_dai_link dai;
	struct snd_soc_card card;
	unsigned int decimation;
};

static u32 imx_pdm_mic_rates[] = { 8000, 16000, 32000, 48000, 64000 };
static struct snd_pcm_hw_constraint_list imx_pdm_mic_rate_constrains = {
	.count = ARRAY_SIZE(imx_pdm_mic_rates),
	.list = imx_pdm_mic_rates,
};
static u32 imx_pdm_mic_channels[] = { 1 };
static struct snd_pcm_hw_constraint_list imx_pdm_mic_channels_constrains = {
	.count = ARRAY_SIZE(imx_pdm_mic_channels),
	.list = imx_pdm_mic_channels,
};

static int imx_pdm_mic_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct snd_soc_card *card = rtd->card;
	int ret;

	ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
			&imx_pdm_mic_rate_constrains);
	if (ret) {
		dev_err(card->dev,
			"fail to set pcm hw rate constrains: %d\n", ret);
		return ret;
	}

	ret = snd_pcm_hw_constraint_list(runtime, 0,
		SNDRV_PCM_HW_PARAM_CHANNELS, &imx_pdm_mic_channels_constrains);
	if (ret) {
		dev_err(card->dev,
			"fail to set pcm hw channels constrains: %d", ret);
		return ret;
	}

	return 0;
}

static int imx_pdm_mic_hw_params(struct snd_pcm_substream *substream,
		struct snd_pcm_hw_params *params)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
	struct snd_soc_card *card = rtd->card;
	struct imx_pdm_data *data = snd_soc_card_get_drvdata(card);
	int ret;

	/* set cpu dai format configuration */
	ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
			SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
	if (ret) {
		dev_err(card->dev, "fail to set cpu dai fmt: %d\n", ret);
		return ret;
	}
	/* set tdm slots only one for now */
	snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0, 1, 32);
	/* Set clock out */
	ret = snd_soc_dai_set_bclk_ratio(cpu_dai, data->decimation);
	if (ret) {
		dev_err(card->dev, "fail to set cpu sysclk: %d\n", ret);
		return ret;
	}

	return 0;
}

static const struct snd_soc_ops imx_pdm_mic_ops = {
	.startup = imx_pdm_mic_startup,
	.hw_params = imx_pdm_mic_hw_params,
};

static int imx_pdm_mic_probe(struct platform_device *pdev)
{
	struct device_node *cpu_np = NULL;
	struct device_node *np = pdev->dev.of_node;
	struct platform_device *cpu_pdev;
	struct imx_pdm_data *data;
	int ret;

	cpu_np = of_parse_phandle(np, "audio-cpu", 0);
	if (!cpu_np) {
		dev_err(&pdev->dev, "cpu dai phandle missing or invalid\n");
		ret = -EINVAL;
		goto fail;
	}

	cpu_pdev = of_find_device_by_node(cpu_np);
	if (!cpu_pdev) {
		dev_err(&pdev->dev, "fail to find SAI platform device\n");
		ret = -EINVAL;
		goto fail;
	}

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data) {
		ret = -ENOMEM;
		goto fail;
	}

	ret = of_property_read_u32(np, "decimation", &data->decimation);
	if (ret < 0) {
		ret = -EINVAL;
		goto fail;
	}

	data->dai.name = "pdm hifi";
	data->dai.stream_name = "pdm hifi";
	data->dai.codec_dai_name = "snd-soc-dummy-dai";
	data->dai.codec_name = "snd-soc-dummy";
	data->dai.cpu_dai_name = dev_name(&cpu_pdev->dev);
	data->dai.platform_of_node = cpu_np;
	data->dai.capture_only = "true";
	data->dai.ops = &imx_pdm_mic_ops;

	data->card.dev = &pdev->dev;
	data->card.owner = THIS_MODULE;

	ret = snd_soc_of_parse_card_name(&data->card, "model");
	if (ret) {
		dev_err(&pdev->dev, "fail to find card model name\n");
		goto fail;
	}

	data->card.num_links = 1;
	data->card.dai_link = &data->dai;

	platform_set_drvdata(pdev, &data->card);
	snd_soc_card_set_drvdata(&data->card, data);

	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
	if (ret) {
		dev_err(&pdev->dev, "snd soc register card failed: %d\n", ret);
		goto fail;
	}

	ret = 0;
fail:
	if (cpu_np)
		of_node_put(cpu_np);

	return ret;
}

static int imx_pdm_mic_remove(struct platform_device *pdev)
{
	struct imx_pdm_data *data = platform_get_drvdata(pdev);
	/* unregister card */
	snd_soc_unregister_card(&data->card);
	return 0;
}

static const struct of_device_id imx_pdm_mic_dt_ids[] = {
	{ .compatible = "fsl,imx-pdm-mic", },
	{ /* sentinel*/ }
};
MODULE_DEVICE_TABLE(of, imx_pdm_mic_dt_ids);

static struct platform_driver imx_pdm_mic_driver = {
	.driver = {
		.name = "imx-pdm-mic",
		.pm = &snd_soc_pm_ops,
		.of_match_table = imx_pdm_mic_dt_ids,
	},
	.probe = imx_pdm_mic_probe,
	.remove = imx_pdm_mic_remove,
};
module_platform_driver(imx_pdm_mic_driver);

MODULE_DESCRIPTION("NXP i.MX PDM mic ASoC machine driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:imx-pdm-mic");
