summaryrefslogtreecommitdiff
path: root/bsd-core/drmP.h
AgeCommit message (Expand)Author
2008-05-27[FreeBSD] Add vblank-rework support and get drivers building.Robert Noland
2008-05-27[FreeBSD] Convert from drm_device_t to struct drm_device for consistency.Eric Anholt
2007-12-02bsd: Replace other occurrences of msleep with mtx_sleepRobert Noland
2007-12-02bsd: Now make secondary vblank workRobert Noland
2007-12-01bsd: Hook secondary vblank support.Robert Noland
2007-11-29Fix up drm_ati_pcigart_infoRobert C. Noland III
2007-11-18Bug #13233: Chase move of agp headers on FreeBSD.Robert Noland
2007-11-14Add new shared header file drm_internal.h.Kristian Høgsberg
2007-08-13Bug #11951: Fix an errno sign inversion on pre-FreeBSD 5.vehemens
2007-07-20Replace DRM_IOCTL_ARGS with (dev, data, file_priv) and remove DRM_DEVICE.Eric Anholt
2007-07-20Replace filp in ioctl arguments with drm_file *file_priv.Eric Anholt
2007-07-20Remove DRM_ERR OS macro.Eric Anholt
2007-07-19FreeBSD warnings cleanup.Eric Anholt
2007-07-18Add dry-coded DRM drawable private information storage for FreeBSD.Eric Anholt
2007-07-16Fix FreeBSD build.Eric Anholt
2007-07-11Made drm_sg_alloc accessible from inside the DRM - drm_sg_alloc_ioctl is the ...Arthur Huillet
2007-05-29Update a bunch of FreeBSD port code.Jung-uk Kim
2006-09-06Use the DRM_INIT_WAITQUEUE argument (needed on Linux) to avoid a warning.Eric Anholt
2006-09-06Put the PCI device/vendor id in the drm_device_t.Eric Anholt
2006-09-06Add a typedef for u64.Eric Anholt
2006-04-18Reorder the DRM_*_AGP enum to match linux's numbers (oops). Fixes i915Eric Anholt
2005-11-08Initial port of savage to FreeBSD for the AGP and !ShadowStatus case. AddsEric Anholt
2005-11-08Fix FreeBSD DRM for latest MGA changes to agp support, which cleans thingsEric Anholt
2005-11-08Catch FreeBSD up to the pcie gart changes. Required minor modification toEric Anholt
2005-09-12Fix the spelling of DRM_AUTH so that the bsd core stuff builds again. NextEric Anholt
2005-09-03convert ioctl flags to use flags instead of separate intsDave Airlie
2005-08-26Previously, drm_get_resource_start() and drm_get_resource_len() wouldEric Anholt
2005-08-26[1] Fix BSD DRM for the nonroot changes. [2] Don't attempt to acquire theEric Anholt
2005-08-17add agp buffer tokenDave Airlie
2005-08-12Fix build after linux-side checkin of master/root-only split. Still onlyEric Anholt
2005-08-05Rename the driver hooks in the DRM to something a little moreEric Anholt
2005-08-04Fix the MGA driver on BSD by passing in the proper chipset flags to theEric Anholt
2005-07-20Add latest r300 support from r300.sf.net CVS. Patch submitted by volodya,Eric Anholt
2005-06-29Get the BSD DRM compiling again after MGA and mapping changes. Note thatEric Anholt
2005-06-14Adds support for PCI cards to MGA DRMIan Romanick
2005-06-06Add a few more bits of Tonnerre's NetBSD port (Still need to deal with theEric Anholt
2005-05-27Modify drm_driver::device_is_agp to return a tri-state value to indicateIan Romanick
2005-05-16Added device_is_agp callback to drm_driver. This function is called by theIan Romanick
2005-04-26Convert BSD code to mostly use bus_dma, the dma abstraction for dealingEric Anholt
2005-04-16Use /*- to begin license blocks in BSD code to reduce diffs against FreeBSDEric Anholt
2005-02-14Use fuword32 for DRM_GET_USER_UNCHECKED when available. May help on 64-bitEric Anholt
2005-02-08Close a race which could allow for privilege escalation by users with DRIEric Anholt
2005-02-05- Implement drm_initmap, and extend it with the resource number to helpEric Anholt
2004-11-07Refine the locking of the DRM. Most significant is covering the driverEric Anholt
2004-11-06Remove some core stuff that ended up being unnecessary.Eric Anholt
2004-11-06Get r128 basically working: Hook up the driver's dma ioctl, use the properEric Anholt
2004-11-06Hook the debug output up to a sysctl, so you can choose to enable atEric Anholt
2004-11-06Commit first pieces of port to OpenBSD, done by Martin Lexa (martin atEric Anholt
2004-11-06Commit WIP of BSD conversion to core model. Compiles for r128, radeon, butEric Anholt
2004-08-17Merged drmfntbl-0-0-1Dave Airlie
d='n403' href='#n403'>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;
				}
				dev_priv->connectors[c]->outputs[j++] = dac2;
				break;
			}
#if 0
			switch (tmds_type) {
			case BIOS_TMDS_TYPE__INTERNAL:
				if (tmdsint == -1) {
					tmdsint = c;
				}
				dev_priv->connectors[c]->outputs[j++] = tmdsint;
				break;
			case BIOS_TMDS_TYPE__EXTERNAL:
				if (tmdsext == -1) {
					tmdsext = c;
				}
				dev_priv->connectors[c]->outputs[j++] = tmdsext;
				break;
			}
#endif
			c++;
		}
	}
	return c;
}

int radeon_ms_outputs_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 numof_connector, i, dac1_present, dac2_present, c = 0;
	int ret;

	dac1_present = dac2_present = 0;
	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);

		if (!dac1_present && dac_type == BIOS_DAC_TYPE__CRT) {
			dev_priv->outputs[c] =
				drm_alloc(sizeof(struct radeon_ms_output),
					  DRM_MEM_DRIVER);
			if (dev_priv->outputs[c] == NULL) {
				radeon_ms_outputs_destroy(dev);
				return -ENOMEM;
			}
			memcpy(dev_priv->outputs[c], &radeon_ms_dac1,
			       sizeof(struct radeon_ms_output));
			dev_priv->outputs[c]->dev = dev;
			dev_priv->outputs[c]->initialize(dev_priv->outputs[c]);
			dac1_present = 1;
			c++;
		}
		if (!dac2_present && dac_type == BIOS_DAC_TYPE__NON_CRT) {
			dev_priv->outputs[c] =
				drm_alloc(sizeof(struct radeon_ms_output),
					  DRM_MEM_DRIVER);
			if (dev_priv->outputs[c] == NULL) {
				radeon_ms_outputs_destroy(dev);
				return -ENOMEM;
			}
			memcpy(dev_priv->outputs[c], &radeon_ms_dac2,
			       sizeof(struct radeon_ms_output));
			dev_priv->outputs[c]->dev = dev;
			dev_priv->outputs[c]->initialize(dev_priv->outputs[c]);
			dac1_present = 1;
			c++;
		}
	}
	return c;
}