/*
 *  hda_i915.c - routines for Haswell HDA controller power well support
 *
 *  This program is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/component.h>
#include <drm/i915_component.h>
#include <sound/core.h>
#include "hda_priv.h"
#include "hda_intel.h"

/* Intel HSW/BDW display HDA controller Extended Mode registers.
 * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display
 * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
 * The values will be lost when the display power well is disabled.
 */
#define AZX_REG_EM4			0x100c
#define AZX_REG_EM5			0x1010

int hda_display_power(struct hda_intel *hda, bool enable)
{
	struct i915_audio_component *acomp = &hda->audio_component;

	if (!acomp->ops)
		return -ENODEV;

	dev_dbg(&hda->chip.pci->dev, "display power %s\n",
		enable ? "enable" : "disable");
	if (enable)
		acomp->ops->get_power(acomp->dev);
	else
		acomp->ops->put_power(acomp->dev);

	return 0;
}

void haswell_set_bclk(struct hda_intel *hda)
{
	int cdclk_freq;
	unsigned int bclk_m, bclk_n;
	struct i915_audio_component *acomp = &hda->audio_component;

	if (!acomp->ops)
		return;

	cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
	switch (cdclk_freq) {
	case 337500:
		bclk_m = 16;
		bclk_n = 225;
		break;

	case 450000:
	default: /* default CDCLK 450MHz */
		bclk_m = 4;
		bclk_n = 75;
		break;

	case 540000:
		bclk_m = 4;
		bclk_n = 90;
		break;

	case 675000:
		bclk_m = 8;
		bclk_n = 225;
		break;
	}

	azx_writew(&hda->chip, EM4, bclk_m);
	azx_writew(&hda->chip, EM5, bclk_n);
}

static int hda_component_master_bind(struct device *dev)
{
	struct snd_card *card = dev_get_drvdata(dev);
	struct azx *chip = card->private_data;
	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
	struct i915_audio_component *acomp = &hda->audio_component;
	int ret;

	ret = component_bind_all(dev, acomp);
	if (ret < 0)
		return ret;

	if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
		      acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
		ret = -EINVAL;
		goto out_unbind;
	}

	/*
	 * Atm, we don't support dynamic unbinding initiated by the child
	 * component, so pin its containing module until we unbind.
	 */
	if (!try_module_get(acomp->ops->owner)) {
		ret = -ENODEV;
		goto out_unbind;
	}

	return 0;

out_unbind:
	component_unbind_all(dev, acomp);

	return ret;
}

static void hda_component_master_unbind(struct device *dev)
{
	struct snd_card *card = dev_get_drvdata(dev);
	struct azx *chip = card->private_data;
	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
	struct i915_audio_component *acomp = &hda->audio_component;

	module_put(acomp->ops->owner);
	component_unbind_all(dev, acomp);
	WARN_ON(acomp->ops || acomp->dev);
}

static const struct component_master_ops hda_component_master_ops = {
	.bind = hda_component_master_bind,
	.unbind = hda_component_master_unbind,
};

static int hda_component_master_match(struct device *dev, void *data)
{
	/* i915 is the only supported component */
	return !strcmp(dev->driver->name, "i915");
}

int hda_i915_init(struct hda_intel *hda)
{
	struct component_match *match = NULL;
	struct device *dev = &hda->chip.pci->dev;
	struct i915_audio_component *acomp = &hda->audio_component;
	int ret;

	component_match_add(dev, &match, hda_component_master_match, hda);
	ret = component_master_add_with_match(dev, &hda_component_master_ops,
					      match);
	if (ret < 0)
		goto out_err;

	/*
	 * Atm, we don't support deferring the component binding, so make sure
	 * i915 is loaded and that the binding successfully completes.
	 */
	request_module("i915");

	if (!acomp->ops) {
		ret = -ENODEV;
		goto out_master_del;
	}

	dev_dbg(dev, "bound to i915 component master\n");

	return 0;
out_master_del:
	component_master_del(dev, &hda_component_master_ops);
out_err:
	dev_err(dev, "failed to add i915 component master (%d)\n", ret);

	return ret;
}

int hda_i915_exit(struct hda_intel *hda)
{
	struct device *dev = &hda->chip.pci->dev;

	component_master_del(dev, &hda_component_master_ops);

	return 0;
}
