summaryrefslogtreecommitdiff
AgeCommit message (Expand)Author
2008-04-06Place highmem pages last in the ttm page array.Thomas Hellstrom
2008-04-06Use clflush() when available for cache flushing.Thomas Hellstrom
2008-04-06[I915] Fix VRAM eviction.Thomas Hellstrom
2008-04-06Fix emergency allocation accounting.Thomas Hellstrom
2008-04-05nv50: primitive i2c interrupt handlerMaarten Maathuis
2008-04-03radeon_ms: add crtc set base callback & fix paletteJerome Glisse
2008-04-03radeon_ms: fixes fb handlingJerome Glisse
2008-04-03nv50: primitive display interrupt handler.Maarten Maathuis
2008-03-31radeon_ms: small fix & cleanup to command checkingJerome Glisse
2008-03-31nouveau: fix return from function..Dave Airlie
2008-03-31radeon_ms: initial pass at command buffer validationJerome Glisse
2008-03-30Initialize the fence::error member.Thomas Hellstrom
2008-03-30[i915] Report buffer state _after_ fence submission to user-space.Thomas Hellstrom
2008-03-30Don't call fence::poll during irq if there are no waiters.Thomas Hellström
2008-03-30nouveau: forgot to add a breakMaarten Maathuis
2008-03-30nouveau: Add ctx values for nv86.Maarten Maathuis
2008-03-30radeon_ms: add hang debuging helper functionsJerome Glisse
2008-03-30drm/r300: fix wait interface mixupDave Airlie
2008-03-29r300: Correctly translate the value for the R300_CMD_WAIT command.Oliver McFadden
2008-03-27radeon_ms: this is a modesetting driver, bring things up to dateJerome Glisse
2008-03-27drm: remove authentication on master exit.Dave Airlie
2008-03-25nouveau: nv20 bios does not initialise PTIMERStuart Bennett
2008-03-24i915: fix oops on agp=offDave Airlie
2008-03-24Merge branch 'r500-fp'Dave Airlie
2008-03-24nouveau: silence warningBen Skeggs
2008-03-24nv40: voodoo - not quite.Ben Skeggs
2008-03-24nv40: allocate massive amount of PRAMIN for grctx on all chipsets.Ben Skeggs
2008-03-21r500: fragment program upload is also used to upload constants.Dave Airlie
2008-03-20Merge branch 'modesetting-101' of ssh://git.freedesktop.org/git/mesa/drm into...Jerome Glisse
2008-03-20radeon_ms: fix fenceJerome Glisse
2008-03-20drm: fixup r500fp submissionDave Airlie
2008-03-20nouveau: do not set on-board timer's numerator/denominator to bad valuesStuart Bennett
2008-03-19RADEON: switch over to new production microcodeAlex Deucher
2008-03-19RADEON: production microcode for all radeons, r1xx-r6xxAlex Deucher
2008-03-19move some more r300 regs into not allowed on r500Dave Airlie
2008-03-18drm: add new rs690 pci idDave Airlie
2008-03-17Evict cached_mapped relocatee before applying reloc.Thomas Hellstrom
2008-03-17drm: add master set/drop protocolDave Airlie
2008-03-17i915: safety check the sarea map still existsDave Airlie
2008-03-17drm: pick correct master for cleaning upDave Airlie
2008-03-17drm: select the correct master to attempt to remove the lock from.Dave Airlie
2008-03-17initial r500 RS and FP register and upload codeDave Airlie
2008-03-17drm/pcigart: fix the pci gart to use the drm_pci wrapper.Dave Airlie
2008-03-16Avoid unnecessary waits for command regulator pause.Thomas Hellstrom
2008-03-16[via] Remove some leftover vars.Thomas Hellstrom
2008-03-16[via] Allow a little larger stride for SG DMA DownloadFromScreen.Thomas Hellstrom
2008-03-16[via] The millionth fixup for the millionth-1 attempt to stabilize the AGPThomas Hellstrom
2008-03-16[via] Fix driver after vblank-rework merge.Thomas Hellstrom
2008-03-16ati: fix rs690 igp gart by allocating the page table in 32-bit memoryDave Airlie
2008-03-16drm/rs690: set AGP_BASE_2 to 0Dave Airlie
a id='n375' href='#n375'>375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
/*
 * Copyright 2007 Jérôme Glisse
 * All Rights Reserved.
 *
 * 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 (including the next
 * paragraph) 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
 * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
 */
/*
 * Authors:
 *    Jérôme Glisse <glisse@freedesktop.org>
 */
#include "radeon_ms.h"

extern struct radeon_ms_output radeon_ms_dac1;
extern struct radeon_ms_output radeon_ms_dac2;
extern const struct drm_output_funcs radeon_ms_output_funcs;

static struct combios_connector_chip_info *
radeon_ms_combios_get_connector_chip_info(struct drm_device *dev, int chip_num)
{
	struct drm_radeon_private *dev_priv = dev->dev_private;
	struct radeon_ms_rom *rom = &dev_priv->rom;
	struct combios_header *header;
	struct combios_connector_table *connector_table;
	struct combios_connector_chip_info *connector_chip_info;
	uint32_t offset;
	int numof_chips, i;

	if (rom->type != ROM_COMBIOS || rom->rom_image == NULL) {
		return NULL;
	}
	header = rom->rom.combios_header;
	offset = header->usPointerToExtendedInitTable2;
	if ((offset + sizeof(struct combios_connector_table)) > rom->rom_size) {
		DRM_INFO("[radeon_ms] wrong COMBIOS connector offset\n");
		return NULL;
	}
	if (!offset) {
		return NULL;
	}
	connector_table = (struct combios_connector_table *)
	                  &rom->rom_image[offset];
	numof_chips = (connector_table->ucConnectorHeader &
		       BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__MASK) >>
		      BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__SHIFT;
	DRM_INFO("[radeon_ms] COMBIOS number of chip: %d (table rev: %d)\n",
		 numof_chips,
		 (connector_table->ucConnectorHeader &
		  BIOS_CONNECTOR_HEADER__TABLE_REVISION__MASK) >>
		 BIOS_CONNECTOR_HEADER__TABLE_REVISION__SHIFT);
	for (i = 0; i < numof_chips; i++) {
		int chip;

		connector_chip_info = &connector_table->sChipConnectorInfo[i];
		chip = (connector_chip_info->ucChipHeader &
			BIOS_CHIPINFO_HEADER__CHIP_NUMBER__MASK) >>
		       BIOS_CHIPINFO_HEADER__CHIP_NUMBER__SHIFT;
		DRM_INFO("[radeon_ms] COMBIOS chip: %d (asked for: %d)\n",
		         chip, chip_num);
		if (chip == chip_num) {
			return connector_chip_info;
		}
	}
	return NULL;
}

static int radeon_combios_get_connector_infos(struct drm_device *dev,
					      int connector_info, 
					      int *connector_type, 
					      int *ddc_line,
					      int *tmds_type,
					      int *dac_type)
{
	struct drm_radeon_private *dev_priv = dev->dev_private;

	*connector_type = (connector_info & BIOS_CONNECTOR_INFO__TYPE__MASK) >>
			  BIOS_CONNECTOR_INFO__TYPE__SHIFT;
	*ddc_line = (connector_info & BIOS_CONNECTOR_INFO__DDC_LINE__MASK) >>
		    BIOS_CONNECTOR_INFO__DDC_LINE__SHIFT;
	*tmds_type = (connector_info & BIOS_CONNECTOR_INFO__TMDS_TYPE__MASK) >>
		     BIOS_CONNECTOR_INFO__TMDS_TYPE__SHIFT;
	*dac_type = (connector_info & BIOS_CONNECTOR_INFO__DAC_TYPE__MASK) >>
		    BIOS_CONNECTOR_INFO__DAC_TYPE__SHIFT;

	/* most XPRESS chips seem to specify DDC_CRT2 for their 
	 * VGA DDC port, however DDC never seems to work on that
	 * port.  Some have reported success on DDC_MONID, so 
	 * lets see what happens with that.
	 */
	if (dev_priv->family == CHIP_RS400 &&
	    *connector_type == BIOS_CONNECTOR_TYPE__CRT &&
	    *ddc_line == BIOS_DDC_LINE__CRT2) {
		*ddc_line = BIOS_DDC_LINE__MONID01;
	}
	/* XPRESS desktop chips seem to have a proprietary
	 * connector listed for DVI-D, try and do the right
	 * thing here.
	 */
	if (dev_priv->family == CHIP_RS400 &&
	    *connector_type == BIOS_CONNECTOR_TYPE__PROPRIETARY) {
		DRM_INFO("[radeon_ms] COMBIOS Proprietary connector "
		         "found, assuming DVI-D\n");
		*dac_type = 2;
	        *tmds_type = BIOS_TMDS_TYPE__EXTERNAL;
		*connector_type = BIOS_CONNECTOR_TYPE__DVI_D;
	}
	return 0;
}

static int radeon_ms_combios_connector_add(struct drm_device *dev,
					   int connector_number,
					   int connector_type,
					   uint32_t i2c_reg)
{
	struct drm_radeon_private *dev_priv = dev->dev_private;
	struct radeon_ms_connector *connector = NULL;
	struct drm_output *output = NULL;

	connector = drm_alloc(sizeof(struct radeon_ms_connector),
			      DRM_MEM_DRIVER);
	if (connector == NULL) {
		radeon_ms_connectors_destroy(dev);
		return -ENOMEM;
	}
	memset(connector, 0, sizeof(struct radeon_ms_connector));
	connector->monitor_type = MT_NONE;
	connector->type = connector_type;
	connector->i2c_reg = i2c_reg;

	switch (connector->type) {
	case CONNECTOR_VGA:
		sprintf(connector->name, "VGA");
		break;
	case CONNECTOR_DVI_I:
		sprintf(connector->name, "DVI-I");
		break;
	case CONNECTOR_DVI_D:
		sprintf(connector->name, "DVI-D");
		break;
	default:
		sprintf(connector->name, "UNKNOWN-CONNECTOR");
		break;
	}

	if (i2c_reg) {
		connector->i2c = radeon_ms_i2c_create(dev,
						      connector->i2c_reg,
						      connector->name);
		if (connector->i2c == NULL) {
			radeon_ms_connectors_destroy(dev);
			return -ENOMEM;
		}
	} else {
		connector->i2c = NULL;
	}

	output = drm_output_create(dev, &radeon_ms_output_funcs,
				   connector->type);
	if (output == NULL) {
		radeon_ms_connectors_destroy(dev);
		return -EINVAL;
	}
	connector->output = output;
	output->driver_private = connector;
	output->possible_crtcs = 0x3;
	dev_priv->connectors[connector_number] = connector;
	return 0;
}

int radeon_ms_combios_get_properties(struct drm_device *dev)
{
	struct drm_radeon_private *dev_priv = dev->dev_private;
	struct radeon_ms_rom *rom = &dev_priv->rom;
	struct combios_pll_block *pll_block;
	struct combios_header *header;
	uint32_t offset;

	if (rom->type != ROM_COMBIOS || rom->rom_image == NULL) {
		return 0;
	}
	header = rom->rom.combios_header;
	offset = header->usPointerToPllInfoBlock;
	if ((offset + sizeof(struct combios_pll_block)) > rom->rom_size) {
		DRM_INFO("[radeon_ms] wrong COMBIOS pll block offset\n");
		return 0;
	}
	if (!offset) {
		return 0;
	}
	pll_block = (struct combios_pll_block *)&rom->rom_image[offset];
	dev_priv->properties.pll_reference_freq = pll_block->usDotClockRefFreq;
	dev_priv->properties.pll_reference_div = pll_block->usDotClockRefDiv;
	dev_priv->properties.pll_min_pll_freq = pll_block->ulDotClockMinFreq;
	dev_priv->properties.pll_max_pll_freq = pll_block->ulDotClockMaxFreq;
	dev_priv->properties.pll_reference_freq *= 10;
	dev_priv->properties.pll_min_pll_freq *= 10;
	dev_priv->properties.pll_max_pll_freq *= 10;
	DRM_INFO("[radeon_ms] COMBIOS pll reference frequency : %d\n",
		 dev_priv->properties.pll_reference_freq);
	DRM_INFO("[radeon_ms] COMBIOS pll reference divider   : %d\n",
		 dev_priv->properties.pll_reference_div);
	DRM_INFO("[radeon_ms] COMBIOS pll minimum frequency   : %d\n",
		 dev_priv->properties.pll_min_pll_freq);
	DRM_INFO("[radeon_ms] COMBIOS pll maximum frequency   : %d\n",
		 dev_priv->properties.pll_max_pll_freq);
	return 1;
}

int radeon_ms_connectors_from_combios(struct drm_device *dev)
{
	struct drm_radeon_private *dev_priv = dev->dev_private;
	struct combios_connector_chip_info *connector_chip_info;
	int connector_type, ddc_line, tmds_type, dac_type;
	int dac1, dac2, tmdsint, tmdsext;
	int numof_connector, i, c = 0, added, j;
	uint32_t i2c_reg;
	int ret;

	dac1 = dac2 = tmdsint = tmdsext = -1;
	connector_chip_info = radeon_ms_combios_get_connector_chip_info(dev, 1);
	if (connector_chip_info == NULL) {
		return -1;
	}
	numof_connector = (connector_chip_info->ucChipHeader &
			   BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__MASK) >>
			  BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__SHIFT;
	DRM_INFO("[radeon_ms] COMBIOS number of connector: %d\n",
	         numof_connector);
	for (i = 0; i < numof_connector; i++) {
		int connector_info = connector_chip_info->sConnectorInfo[i];

		ret = radeon_combios_get_connector_infos(dev,
							 connector_info, 
							 &connector_type, 
							 &ddc_line,
							 &tmds_type,
							 &dac_type);

		switch (ddc_line) {
		case BIOS_DDC_LINE__MONID01:
			i2c_reg = GPIO_MONID;
			break;
		case BIOS_DDC_LINE__DVI:
			i2c_reg =  GPIO_DVI_DDC;
			break;
		case BIOS_DDC_LINE__VGA:
			i2c_reg = GPIO_DDC1;
			break;
		case BIOS_DDC_LINE__CRT2:
			i2c_reg = GPIO_CRT2_DDC;
			break;
		case BIOS_DDC_LINE__GPIOPAD:
			i2c_reg = VIPPAD_EN;
			break;
		case BIOS_DDC_LINE__ZV_LCDPAD:
			i2c_reg = VIPPAD1_EN;
			break;
		default:
			i2c_reg = 0;
			break;
		}
		added = 0;
		switch (connector_type) {
		case BIOS_CONNECTOR_TYPE__CRT:
			ret = radeon_ms_combios_connector_add(dev, c,
							      CONNECTOR_VGA,
							      i2c_reg);
			if (ret) {
				return ret;
			}
			added = 1;
			break;
		case BIOS_CONNECTOR_TYPE__DVI_I:
			ret = radeon_ms_combios_connector_add(dev, c,
							      CONNECTOR_DVI_I,
							      i2c_reg);
			if (ret) {
				return ret;
			}
			added = 1;
			break;
		case BIOS_CONNECTOR_TYPE__DVI_D:
			ret = radeon_ms_combios_connector_add(dev, c,
							      CONNECTOR_DVI_D,
							      i2c_reg);
			if (ret) {
				return ret;
			}
			added = 1;
			break;
		default:
			break;
		}
		if (added) {
			j = 0;
			/* find to which output this connector is associated 
			 * by following same algo as in:
			 * radeon_ms_outputs_from_combios*/
			switch (dac_type) {
			case BIOS_DAC_TYPE__CRT:
				if (dac1 == -1) {
					dac1 = c;
				}
				dev_priv->connectors[c]->outputs[j++] = dac1;
				break;
			case BIOS_DAC_TYPE__NON_CRT:
				if (dac2 == -1) {
					dac2 = c;
				}