/*
 * Copyright (c) Intel Corp. 2007.
 * All Rights Reserved.
 *
 * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
 * develop this driver.
 *
 * This file is part of the Carillo Ranch video subsystem driver.
 * The Carillo Ranch video subsystem driver 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.
 *
 * The Carillo Ranch video subsystem driver 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 driver; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Authors:
 *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
 *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include "vermilion.h"

/* The PLL Clock register sits on Host bridge */
#define CRVML_DEVICE_MCH   0x5001
#define CRVML_REG_MCHBAR   0x44
#define CRVML_REG_MCHEN    0x54
#define CRVML_MCHEN_BIT    (1 << 28)
#define CRVML_MCHMAP_SIZE  4096
#define CRVML_REG_CLOCK    0xc3c
#define CRVML_CLOCK_SHIFT  8
#define CRVML_CLOCK_MASK   0x00000f00

static struct pci_dev *mch_dev;
static u32 mch_bar;
static void __iomem *mch_regs_base;
static u32 saved_clock;

static const unsigned crvml_clocks[] = {
	6750,
	13500,
	27000,
	29700,
	37125,
	54000,
	59400,
	74250,
	120000
	    /*
	     * There are more clocks, but they are disabled on the CR board.
	     */
};

static const u32 crvml_clock_bits[] = {
	0x0a,
	0x09,
	0x08,
	0x07,
	0x06,
	0x05,
	0x04,
	0x03,
	0x0b
};

static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);

static int crvml_sys_restore(struct vml_sys *sys)
{
	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;

	iowrite32(saved_clock, clock_reg);
	ioread32(clock_reg);

	return 0;
}

static int crvml_sys_save(struct vml_sys *sys)
{
	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;

	saved_clock = ioread32(clock_reg);

	return 0;
}

static int crvml_nearest_index(const struct vml_sys *sys, int clock)
{
	int i;
	int cur_index = 0;
	int cur_diff;
	int diff;

	cur_diff = clock - crvml_clocks[0];
	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
	for (i = 1; i < crvml_num_clocks; ++i) {
		diff = clock - crvml_clocks[i];
		diff = (diff < 0) ? -diff : diff;
		if (diff < cur_diff) {
			cur_index = i;
			cur_diff = diff;
		}
	}
	return cur_index;
}

static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
{
	return crvml_clocks[crvml_nearest_index(sys, clock)];
}

static int crvml_set_clock(struct vml_sys *sys, int clock)
{
	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
	int index;
	u32 clock_val;

	index = crvml_nearest_index(sys, clock);

	if (crvml_clocks[index] != clock)
		return -EINVAL;

	clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
	clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
	iowrite32(clock_val, clock_reg);
	ioread32(clock_reg);

	return 0;
}

static struct vml_sys cr_pll_ops = {
	.name = "Carillo Ranch",
	.save = crvml_sys_save,
	.restore = crvml_sys_restore,
	.set_clock = crvml_set_clock,
	.nearest_clock = crvml_nearest_clock,
};

static int __init cr_pll_init(void)
{
	int err;
	u32 dev_en;

	mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
					CRVML_DEVICE_MCH, NULL);
	if (!mch_dev) {
		printk(KERN_ERR
		       "Could not find Carillo Ranch MCH device.\n");
		return -ENODEV;
	}

	pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
	if (!(dev_en & CRVML_MCHEN_BIT)) {
		printk(KERN_ERR
		       "Carillo Ranch MCH device was not enabled.\n");
		pci_dev_put(mch_dev);
		return -ENODEV;
	}

	pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
			      &mch_bar);
	mch_regs_base =
	    ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
	if (!mch_regs_base) {
		printk(KERN_ERR
		       "Carillo Ranch MCH device was not enabled.\n");
		pci_dev_put(mch_dev);
		return -ENODEV;
	}

	err = vmlfb_register_subsys(&cr_pll_ops);
	if (err) {
		printk(KERN_ERR
		       "Carillo Ranch failed to initialize vml_sys.\n");
		iounmap(mch_regs_base);
		pci_dev_put(mch_dev);
		return err;
	}

	return 0;
}

static void __exit cr_pll_exit(void)
{
	vmlfb_unregister_subsys(&cr_pll_ops);

	iounmap(mch_regs_base);
	pci_dev_put(mch_dev);
}

module_init(cr_pll_init);
module_exit(cr_pll_exit);

MODULE_AUTHOR("Tungsten Graphics Inc.");
MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
MODULE_LICENSE("GPL");
