/*
 * Copyright 2009 Red Hat Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Author: Ben Skeggs
 */

#include "drmP.h"
#include "drm.h"
#include "drm_crtc_helper.h"

#include "nouveau_drv.h"
#include "nouveau_fb.h"
#include "nouveau_hw.h"
#include "nouveau_encoder.h"
#include "nouveau_connector.h"

static void
nv04_display_store_initial_head_owner(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	if (dev_priv->chipset != 0x11) {
		dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
		return;
	}

	/* reading CR44 is broken on nv11, so we attempt to infer it */
	if (nvReadMC(dev, NV_PBUS_DEBUG_1) & (1 << 28))	/* heads tied, restore both */
		dev_priv->crtc_owner = 0x4;
	else {
		uint8_t slaved_on_A, slaved_on_B;
		bool tvA = false;
		bool tvB = false;

		slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
									0x80;
		if (slaved_on_B)
			tvB = !(NVReadVgaCrtc(dev, 1, NV_CIO_CRE_LCD__INDEX) &
					MASK(NV_CIO_CRE_LCD_LCD_SELECT));

		slaved_on_A = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX) &
									0x80;
		if (slaved_on_A)
			tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
					MASK(NV_CIO_CRE_LCD_LCD_SELECT));

		if (slaved_on_A && !tvA)
			dev_priv->crtc_owner = 0x0;
		else if (slaved_on_B && !tvB)
			dev_priv->crtc_owner = 0x3;
		else if (slaved_on_A)
			dev_priv->crtc_owner = 0x0;
		else if (slaved_on_B)
			dev_priv->crtc_owner = 0x3;
		else
			dev_priv->crtc_owner = 0x0;
	}
}

int
nv04_display_early_init(struct drm_device *dev)
{
	/* Make the I2C buses accessible. */
	if (!nv_gf4_disp_arch(dev)) {
		uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);

		if (!(pmc_enable & 1))
			nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1);
	}

	/* Unlock the VGA CRTCs. */
	NVLockVgaCrtcs(dev, false);

	/* Make sure the CRTCs aren't in slaved mode. */
	if (nv_two_heads(dev)) {
		nv04_display_store_initial_head_owner(dev);
		NVSetOwner(dev, 0);
	}

	return 0;
}

void
nv04_display_late_takedown(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;

	if (nv_two_heads(dev))
		NVSetOwner(dev, dev_priv->crtc_owner);

	NVLockVgaCrtcs(dev, true);
}

int
nv04_display_create(struct drm_device *dev)
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct dcb_table *dcb = &dev_priv->vbios.dcb;
	struct drm_connector *connector, *ct;
	struct drm_encoder *encoder;
	struct drm_crtc *crtc;
	int i, ret;

	NV_DEBUG_KMS(dev, "\n");

	nouveau_hw_save_vga_fonts(dev, 1);

	drm_mode_config_init(dev);
	drm_mode_create_scaling_mode_property(dev);
	drm_mode_create_dithering_property(dev);

	dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;

	dev->mode_config.min_width = 0;
	dev->mode_config.min_height = 0;
	switch (dev_priv->card_type) {
	case NV_04:
		dev->mode_config.max_width = 2048;
		dev->mode_config.max_height = 2048;
		break;
	default:
		dev->mode_config.max_width = 4096;
		dev->mode_config.max_height = 4096;
		break;
	}

	dev->mode_config.fb_base = dev_priv->fb_phys;

	nv04_crtc_create(dev, 0);
	if (nv_two_heads(dev))
		nv04_crtc_create(dev, 1);

	for (i = 0; i < dcb->entries; i++) {
		struct dcb_entry *dcbent = &dcb->entry[i];

		connector = nouveau_connector_create(dev, dcbent->connector);
		if (IS_ERR(connector))
			continue;

		switch (dcbent->type) {
		case OUTPUT_ANALOG:
			ret = nv04_dac_create(connector, dcbent);
			break;
		case OUTPUT_LVDS:
		case OUTPUT_TMDS:
			ret = nv04_dfp_create(connector, dcbent);
			break;
		case OUTPUT_TV:
			if (dcbent->location == DCB_LOC_ON_CHIP)
				ret = nv17_tv_create(connector, dcbent);
			else
				ret = nv04_tv_create(connector, dcbent);
			break;
		default:
			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
			continue;
		}

		if (ret)
			continue;
	}

	list_for_each_entry_safe(connector, ct,
				 &dev->mode_config.connector_list, head) {
		if (!connector->encoder_ids[0]) {
			NV_WARN(dev, "%s has no encoders, removing\n",
				drm_get_connector_name(connector));
			connector->funcs->destroy(connector);
		}
	}

	/* Save previous state */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		crtc->funcs->save(crtc);

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		struct drm_encoder_helper_funcs *func = encoder->helper_private;

		func->save(encoder);
	}

	return 0;
}

void
nv04_display_destroy(struct drm_device *dev)
{
	struct drm_encoder *encoder;
	struct drm_crtc *crtc;

	NV_DEBUG_KMS(dev, "\n");

	/* Turn every CRTC off. */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		struct drm_mode_set modeset = {
			.crtc = crtc,
		};

		crtc->funcs->set_config(&modeset);
	}

	/* Restore state */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		struct drm_encoder_helper_funcs *func = encoder->helper_private;

		func->restore(encoder);
	}

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		crtc->funcs->restore(crtc);

	drm_mode_config_cleanup(dev);

	nouveau_hw_save_vga_fonts(dev, 0);
}

int
nv04_display_init(struct drm_device *dev)
{
	struct drm_encoder *encoder;
	struct drm_crtc *crtc;

	/* meh.. modeset apparently doesn't setup all the regs and depends
	 * on pre-existing state, for now load the state of the card *before*
	 * nouveau was loaded, and then do a modeset.
	 *
	 * best thing to do probably is to make save/restore routines not
	 * save/restore "pre-load" state, but more general so we can save
	 * on suspend too.
	 */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
		struct drm_encoder_helper_funcs *func = encoder->helper_private;

		func->restore(encoder);
	}

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		crtc->funcs->restore(crtc);

	return 0;
}

