radeon_ms: add rom parsing & adapt code

Add rom (only combios for now) parsing and use informations
retrieve instead of hardcoded table. Shuffle code around a
bit.
This commit is contained in:
Jerome Glisse 2008-01-15 14:05:25 +01:00 committed by John Doe
parent e6fc47129f
commit f1f934c8c9
20 changed files with 1300 additions and 157 deletions

View file

@ -39,7 +39,8 @@ radeon_ms-objs := radeon_ms_drv.o radeon_ms_drm.o radeon_ms_family.o \
radeon_ms_bus.o radeon_ms_fence.o \
radeon_ms_cp.o radeon_ms_cp_mc.o radeon_ms_i2c.o \
radeon_ms_output.o radeon_ms_crtc.o radeon_ms_fb.o \
radeon_ms_exec.o radeon_ms_gpu.o radeon_ms_dac.o
radeon_ms_exec.o radeon_ms_gpu.o radeon_ms_dac.o \
radeon_ms_properties.o radeon_ms_rom.o radeon_ms_combios.o
sis-objs := sis_drv.o sis_mm.o
ffb-objs := ffb_drv.o ffb_context.o
savage-objs := savage_drv.o savage_bci.o savage_state.o

View file

@ -0,0 +1 @@
../shared-core/radeon_ms_combios.c

View file

@ -0,0 +1 @@
../shared-core/radeon_ms_combios.h

View file

@ -0,0 +1 @@
../shared-core/radeon_ms_properties.c

View file

@ -0,0 +1 @@
../shared-core/radeon_ms_properties.h

1
linux-core/radeon_ms_rom.c Symbolic link
View file

@ -0,0 +1 @@
../shared-core/radeon_ms_rom.c

1
linux-core/radeon_ms_rom.h Symbolic link
View file

@ -0,0 +1 @@
../shared-core/radeon_ms_rom.h

View file

@ -33,6 +33,8 @@
#include "radeon_ms_drv.h"
#include "radeon_ms_reg.h"
#include "radeon_ms_drm.h"
#include "radeon_ms_rom.h"
#include "radeon_ms_properties.h"
#define DRIVER_AUTHOR "Jerome Glisse, Dave Airlie, Gareth Hughes, "\
"Keith Whitwell, others."
@ -43,10 +45,6 @@
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
#define RADEON_PAGE_SIZE 4096
#define RADEON_MAX_CONNECTORS 8
#define RADEON_MAX_OUTPUTS 8
enum radeon_bus_type {
RADEON_PCI = 0x10000,
RADEON_AGP = 0x20000,
@ -154,20 +152,6 @@ struct radeon_ms_output {
struct radeon_state *state);
};
struct radeon_ms_properties {
uint16_t subvendor;
uint16_t subdevice;
int16_t pll_reference_freq;
int32_t pll_min_pll_freq;
int32_t pll_max_pll_freq;
char pll_use_bios;
char pll_dummy_reads;
char pll_delay;
char pll_r300_errata;
struct radeon_ms_output *outputs[RADEON_MAX_OUTPUTS];
struct radeon_ms_connector *connectors[RADEON_MAX_CONNECTORS];
};
struct radeon_state {
/* memory */
uint32_t config_aper_0_base;
@ -310,7 +294,6 @@ struct drm_radeon_private {
/* card family */
uint32_t usec_timeout;
uint32_t family;
struct radeon_ms_properties *properties;
struct radeon_ms_output *outputs[RADEON_MAX_OUTPUTS];
struct radeon_ms_connector *connectors[RADEON_MAX_CONNECTORS];
/* drm map (MMIO, FB) */
@ -342,6 +325,9 @@ struct drm_radeon_private {
uint8_t cp_ready;
uint8_t bus_ready;
uint8_t write_back;
/* abstract asic specific structures */
struct radeon_ms_rom rom;
struct radeon_ms_properties properties;
};
@ -369,6 +355,11 @@ int radeon_ms_pcie_init(struct drm_device *dev);
void radeon_ms_pcie_restore(struct drm_device *dev, struct radeon_state *state);
void radeon_ms_pcie_save(struct drm_device *dev, struct radeon_state *state);
/* radeon_ms_combios.c */
int radeon_ms_combios_get_properties(struct drm_device *dev);
int radeon_ms_connectors_from_combios(struct drm_device *dev);
int radeon_ms_outputs_from_combios(struct drm_device *dev);
/* radeon_ms_compat.c */
long radeon_ms_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg);
@ -475,12 +466,21 @@ void radeon_ms_irq_uninstall(struct drm_device * dev);
/* radeon_ms_output.c */
void radeon_ms_connectors_destroy(struct drm_device *dev);
int radeon_ms_connectors_from_properties(struct drm_device *dev);
int radeon_ms_connectors_from_rom(struct drm_device *dev);
void radeon_ms_outputs_destroy(struct drm_device *dev);
int radeon_ms_outputs_from_properties(struct drm_device *dev);
int radeon_ms_outputs_from_rom(struct drm_device *dev);
void radeon_ms_outputs_restore(struct drm_device *dev,
struct radeon_state *state);
void radeon_ms_outputs_save(struct drm_device *dev, struct radeon_state *state);
/* radeon_ms_properties.c */
int radeon_ms_properties_init(struct drm_device *dev);
/* radeon_ms_rom.c */
int radeon_ms_rom_get_properties(struct drm_device *dev);
int radeon_ms_rom_init(struct drm_device *dev);
/* radeon_ms_state.c */
void radeon_ms_state_save(struct drm_device *dev, struct radeon_state *state);
void radeon_ms_state_restore(struct drm_device *dev,
@ -545,7 +545,7 @@ static __inline__ void pll_index_errata(struct drm_radeon_private *dev_priv)
/* This workaround is necessary on rv200 and RS200 or PLL
* reads may return garbage (among others...)
*/
if (dev_priv->properties->pll_dummy_reads) {
if (dev_priv->properties.pll_dummy_reads) {
tmp = MMIO_R(CLOCK_CNTL_DATA);
tmp = MMIO_R(CRTC_GEN_CNTL);
}
@ -554,7 +554,7 @@ static __inline__ void pll_index_errata(struct drm_radeon_private *dev_priv)
* CLOCK_CNTL_INDEX register access. If not, register reads afterward
* may not be correct.
*/
if (dev_priv->properties->pll_r300_errata) {
if (dev_priv->properties.pll_r300_errata) {
tmp = save = MMIO_R(CLOCK_CNTL_INDEX);
tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_WR_EN;
@ -569,7 +569,7 @@ static __inline__ void pll_data_errata(struct drm_radeon_private *dev_priv)
/* This workarounds is necessary on RV100, RS100 and RS200 chips
* or the chip could hang on a subsequent access
*/
if (dev_priv->properties->pll_delay) {
if (dev_priv->properties.pll_delay) {
/* we can't deal with posted writes here ... */
udelay(5000);
}

View file

@ -0,0 +1,396 @@
/*
* 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;
if (i2c_reg) {
connector->i2c = radeon_ms_i2c_create(dev,
connector->i2c_reg,
connector->type);
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,
ConnectorVGA,
i2c_reg);
if (ret) {
return ret;
}
added = 1;
break;
case BIOS_CONNECTOR_TYPE__DVI_I:
ret = radeon_ms_combios_connector_add(dev, c,
ConnectorDVII,
i2c_reg);
if (ret) {
return ret;
}
added = 1;
break;
case BIOS_CONNECTOR_TYPE__DVI_D:
ret = radeon_ms_combios_connector_add(dev, c,
ConnectorDVID,
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;
}

View file

@ -0,0 +1,385 @@
/*
* Copyright 2006-2007 Advanced Micro Devices, Inc.
* Copyright 2007 Jérôme Glisse
*
* 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.
*/
/*
* Authors:
* Jérôme Glisse <glisse@freedesktop.org>
*/
#ifndef __RADEON_MS_COMBIOS_H__
#define __RADEON_MS_COMBIOS_H__
#pragma pack(1)
#define ROM_HEADER 0x48
struct combios_header
{
uint8_t ucTypeDefinition;
uint8_t ucExtFunctionCode;
uint8_t ucOemID1;
uint8_t ucOemID2;
uint8_t ucBiosMajorRev;
uint8_t ucBiosMinorRev;
uint16_t usStructureSize;
uint16_t usPointerToSmi;
uint16_t usPointerToPmid;
uint16_t usPointerToInitTable;
uint16_t usPointerToCrcChecksumBlock;
uint16_t usPointerToConfigFilename;
uint16_t usPointerToLogonMessage;
uint16_t usPointerToMiscInfo;
uint16_t usPciBusDevInitCode;
uint16_t usBiosRuntimeSegmentAddress;
uint16_t usIoBaseAddress;
uint16_t usSubsystemVendorID;
uint16_t usSubsystemID;
uint16_t usPostVendorID;
uint16_t usInt10Offset;
uint16_t usInt10Segment;
uint16_t usMonitorInfo;
uint16_t usPointerToConfigBlock;
uint16_t usPointerToDacDelayInfo;
uint16_t usPointerToCapDataStruct;
uint16_t usPointerToInternalCrtTables;
uint16_t usPointerToPllInfoBlock;
uint16_t usPointerToTVInfoTable;
uint16_t usPointerToDFPInfoTable;
uint16_t usPointerToHWConfigTable;
uint16_t usPointerToMMConfigTable;
uint32_t ulTVStdPatchTableSignature;
uint16_t usPointerToTVStdPatchTable;
uint16_t usPointerToPanelInfoTable;
uint16_t usPointerToAsicInfoTable;
uint16_t usPointerToAuroraInfoTable;
uint16_t usPointerToPllInitTable;
uint16_t usPointerToMemoryConfigTable;
uint16_t usPointerToSaveMaskTable;
uint16_t usPointerHardCodedEdid;
uint16_t usPointerToExtendedInitTable1;
uint16_t usPointerToExtendedInitTable2;
uint16_t usPointerToDynamicClkTable;
uint16_t usPointerToReservedMemoryTable;
uint16_t usPointerToBridgetInitTable;
uint16_t usPointerToExtTMDSInitTable;
uint16_t usPointerToMemClkInfoTable;
uint16_t usPointerToExtDACTable;
uint16_t usPointerToMiscInfoTable;
};
struct combios_pll_block
{
/* Usually 6 */
uint8_t ucPLLBiosVersion;
/* Size in bytes */
uint8_t ucStructureSize;
/* Dot clock entry used for accelerated modes */
uint8_t ucDotClockEntry;
/* Dot clock entry used for extended VGA modes */
uint8_t ucDotClockEntryVga;
/* Offset into internal clock table used for by VGA parameter table */
uint16_t usPointerToInternalClock;
/* Offset into actual programmed frequency table at POST */
uint16_t usPointerToFreqTable;
/* XCLK setting, (memory clock in 10 KHz units) */
uint16_t usXclkSetting;
/* MCLK setting, (engine clock in 10 KHz units) */
uint16_t usMclkSetting;
/* Number of PLL information block to follow, currently value is 3 */
uint8_t ucPllInfoBlockNumber;
/* Size of each PLL information block */
uint8_t ucPllInfoBlockSize;
/* Reference frequency of the dot clock */
uint16_t usDotClockRefFreq;
/* Reference Divider of the dot clock */
uint16_t usDotClockRefDiv;
/* Min Frequency supported before post divider for the dot clock */
uint32_t ulDotClockMinFreq;
/* Max Frequency can be supported for the dot clock */
uint32_t ulDotClockMaxFreq;
/* Reference frequency of the MCLK, engine clock */
uint16_t usMclkRefFreq;
/* Reference Divider of the MCLK, engine clock */
uint16_t usMclkRefDiv;
/* Min Frequency supported before post divider for MCLK, engine clock */
uint32_t ulMclkMinFreq;
/* Max Frequency can be supported for the MCLK, engine clock */
uint32_t ulMclkMaxFreq;
/* Reference frequency of the XCLK, memory clock */
uint16_t usXclkRefFreq;
/* Reference Divider of the XCLK, memory clock */
uint16_t usXclkRefDiv;
/* Min Frequency supported before post divider for XCLK, memory clock */
uint32_t ulXclkMinFreq;
/* Max Frequency can be supported for the XCLK, memory clock */
uint32_t ulXclkMaxFreq;
/*this is the PLL Information Table Extended structure version 10 */
uint8_t ucNumberOfExtendedPllBlocks;
uint8_t ucSizePLLDefinition;
uint16_t ulCrystalFrequencyPixelClock_pll;
uint32_t ulMinInputPixelClockPLLFrequency;
uint32_t ulMaxInputPixelClockPLLFrequency;
uint32_t ulMinOutputPixelClockPLLFrequency;
uint32_t ulMaxOutputPixelClockPLLFrequency;
/*version 11 */
uint16_t ulCrystalFrequencyEngineClock_pll;
uint32_t ulMinInputFrequencyEngineClock_pll;
uint32_t ulMaxInputFrequencyEngineClock_pll;
uint32_t ulMinOutputFrequencyEngineClock_pll;
uint32_t ulMaxOutputFrequencyEngineClock_pll;
uint16_t ulCrystalFrequencyMemoryClock_pll;
uint32_t ulMinInputFrequencyMemoryClock_pll;
uint32_t ulMaxInputFrequencyMemoryClock_pll;
uint32_t ulMinOutputFrequencyMemoryClock_pll;
uint32_t ulMaxOutputFrequencyMemoryClock_pll;
uint32_t ulMaximumDACOutputFrequency;
};
#define MAX_NO_OF_LCD_RES_TIMING 25
struct panel_information_table
{
uint8_t ucPanelIdentification;
uint8_t ucPanelIDString[24];
uint16_t usHorizontalSize;
uint16_t usVerticalSize;
uint16_t usFlatPanelType;
uint8_t ucRedBitsPerPrimary;
uint8_t ucGreenBitsPerPrimary;
uint8_t ucBlueBitsPerPrimary;
uint8_t ucReservedBitsPerPrimary;
uint8_t ucPanelCaps;
uint8_t ucPowerSequenceDelayStepsInMS;
uint8_t ucSupportedRefreshRateExtended;
uint16_t usExtendedPanelInfoTable;
uint16_t usPtrToHalfFrameBufferInformationTable;
uint16_t usVccOntoBlOn;
uint16_t usOffDelay;
uint16_t usRefDiv;
uint8_t ucPostDiv;
uint16_t usFeedBackDiv;
uint8_t ucSpreadSpectrumType;
uint16_t usSpreadSpectrumPercentage;
uint8_t ucBackLightLevel;
uint8_t ucBiasLevel;
uint8_t ucPowerSequenceDelay;
uint32_t ulPanelData;
uint8_t ucPanelRefreshRateData;
uint16_t usSupportedRefreshRate;
uint16_t usModeTableOffset[MAX_NO_OF_LCD_RES_TIMING];
};
struct extended_panel_info_table
{
uint8_t ucExtendedPanelInfoTableVer;
uint8_t ucSSDelay;
uint8_t ucSSStepSizeIndex;
};
struct lcd_mode_table_center
{
uint16_t usHorizontalRes;
uint16_t usVerticalRes;
uint8_t ucModeType;
uint16_t usOffset2ExpParamTable;
uint16_t usOffset2TvParamTable;
uint16_t usPixelClock;
uint16_t usPixelClockAdjustment;
uint16_t usFpPos;
uint8_t ucReserved;
uint8_t ucMiscBits;
uint16_t usCrtcHTotal;
uint16_t usCrtcHDisp;
uint16_t usCrtcHSyncStrt;
uint8_t ucCrtcHSyncWid;
uint16_t usCrtcVTotal;
uint16_t usCrtcVDisp;
uint16_t usCrtcVSyncStrt;
uint8_t ucOvrWidTop;
};
struct lcd_mode_table_exp
{
uint16_t usPixelClock;
uint16_t usPixelClockAdjustment;
uint16_t usFpPos;
uint8_t ucReserved;
uint8_t ucMiscBits;
uint16_t usCrtcHTotal;
uint16_t usCrtcHDisp;
uint16_t usCrtcHSyncStrt;
uint8_t ucCrtcHSyncWid;
uint16_t usCrtcVTotal;
uint16_t usCrtcVDisp;
uint16_t usCrtcVSyncStrt;
uint8_t ucOvrWidTop;
uint16_t usHorizontalBlendRatio;
uint32_t ulVgaVertStretching;
uint16_t usCopVertStretching;
uint16_t usVgaExtVertStretching;
};
struct tmds_pll_cntl_block
{
uint16_t usClockUpperRange;
uint32_t ulPllSetting;
};
#define MAX_PLL_CNTL_ENTRIES 8
struct combios_dfp_info_table
{
uint8_t ucDFPInfoTableRev;
uint8_t ucDFPInfoTableSize;
uint16_t usOffsetDetailedTimingTable;
uint8_t ucReserved;
uint8_t ucNumberOfClockRanges;
uint16_t usMaxPixelClock;
uint32_t ulInitValueTmdsPllCntl;
uint32_t ulFinalValueTmdsPllCntl;
struct tmds_pll_cntl_block sTmdsPllCntlBlock[MAX_PLL_CNTL_ENTRIES];
};
struct combios_exttmds_table_header
{
uint8_t ucTableRev;
uint16_t usTableSize;
uint8_t ucNoBlocks;
};
struct combios_exttmds_block_header
{
uint16_t usMaxFreq;
uint8_t ucI2CSlaveAddr;
uint8_t ucI2CLine;
uint8_t ucConnectorId;
uint8_t ucFlags;
};
/* Connector table - applicable from Piglet and later ASICs
byte 0 (embedded revision)
[7:4] = number of chips (valid number 1 - 15)
[3:0] = revision number of table (valid number 1 - 15)
byte 1 (Chip info)
[7:4] = chip number, max. 15 (valid number 1 - 15)
[3:0] = number of connectors for that chip, (valid number 1 - 15)
(number of connectors = number of 'Connector info' entries
for that chip)
byte 2,3 (Connector info)
[15:12] - connector type
= 0 - no connector
= 1 - proprietary
= 2 - CRT
= 3 - DVI-I
= 4 - DVI-D
= 5-15 - reserved for future expansion
[11:8] - DDC line pair used for that connector
= 0 - no DDC
= 1 - MONID 0/1
= 2 - DVI_DDC
= 3 - VGA_DDC
= 4 - CRT2_DDC
= 5-15 - reserved for future expansion
[5] - bit indicating presence of multiplexer for TV,CRT2
[7:6] - reserved for future expansion
[4] - TMDS type
= 0 - internal TMDS
= 1 - external TMDS
[3:1] - reserved for future expansion
[0] - DAC associated with that connector
= 0 - CRT DAC
= 1 - non-CRT DAC (e.g. TV DAC, external DAC ..)
byte 4,5,6... - byte 4,5 can be another "Connector info" word
describing another connector
- or byte 5 is a "Chip info" byte for anther chip,
then start with byte 5,6 to describe connectors
for that chip
- or byte 5 = 0 if all connectors for all chips on
board have been described, no more connector left
to describe.
*/
#define BIOS_CONNECTOR_INFO__TYPE__MASK 0xF000
#define BIOS_CONNECTOR_INFO__TYPE__SHIFT 0x0000000C
#define BIOS_CONNECTOR_TYPE__NONE 0x00000000
#define BIOS_CONNECTOR_TYPE__PROPRIETARY 0x00000001
#define BIOS_CONNECTOR_TYPE__CRT 0x00000002
#define BIOS_CONNECTOR_TYPE__DVI_I 0x00000003
#define BIOS_CONNECTOR_TYPE__DVI_D 0x00000004
#define BIOS_CONNECTOR_INFO__DDC_LINE__MASK 0x0F00
#define BIOS_CONNECTOR_INFO__DDC_LINE__SHIFT 0x00000008
#define BIOS_DDC_LINE__NONE 0x00000000
#define BIOS_DDC_LINE__MONID01 0x00000001
#define BIOS_DDC_LINE__DVI 0x00000002
#define BIOS_DDC_LINE__VGA 0x00000003
#define BIOS_DDC_LINE__CRT2 0x00000004
#define BIOS_DDC_LINE__GPIOPAD 0x00000005
#define BIOS_DDC_LINE__ZV_LCDPAD 0x00000006
#define BIOS_CONNECTOR_INFO__TMDS_TYPE__MASK 0x0010
#define BIOS_CONNECTOR_INFO__TMDS_TYPE__SHIFT 0x00000004
#define BIOS_TMDS_TYPE__INTERNAL 0x00000000
#define BIOS_TMDS_TYPE__EXTERNAL 0x00000001
#define BIOS_CONNECTOR_INFO__DAC_TYPE__MASK 0x0001
#define BIOS_CONNECTOR_INFO__DAC_TYPE__SHIFT 0x00000000
#define BIOS_DAC_TYPE__CRT 0x00000000
#define BIOS_DAC_TYPE__NON_CRT 0x00000001
#define BIOS_CONNECTOR_INFO__MUX_MASK 0x00000020
#define BIOS_CONNECTOR_INFO__MUX_SHIFT 0x00000005
#define BIOS_CHIPINFO_HEADER__CHIP_NUMBER__MASK 0xF0
#define BIOS_CHIPINFO_HEADER__CHIP_NUMBER__SHIFT 0x00000004
#define BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__MASK 0x0F
#define BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__SHIFT 0x00000000
#define BIOS_CHIPINFO__MAX_NUMBER_OF_CONNECTORS 0x00000010
struct combios_connector_chip_info
{
uint8_t ucChipHeader;
uint16_t sConnectorInfo[BIOS_CHIPINFO__MAX_NUMBER_OF_CONNECTORS];
};
#define BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__MASK 0xF0
#define BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__SHIFT 0x00000004
#define BIOS_CONNECTOR_HEADER__TABLE_REVISION__MASK 0x0F
#define BIOS_CONNECTOR_HEADER__TABLE_REVISION__SHIFT 0x00000000
struct combios_connector_table
{
uint8_t ucConnectorHeader;
struct combios_connector_chip_info sChipConnectorInfo[0x10];
};
#pragma pack()
int combios_parse(unsigned char *rom, struct combios_header *header);
#endif

View file

@ -380,23 +380,26 @@ static void radeon_ms_crtc_mode_prepare(struct drm_crtc *crtc)
}
/* compute PLL registers values for requested video mode */
static int radeon_pll1_constraint(int clock, int rdiv,
static int radeon_pll1_constraint(struct drm_device *dev,
int clock, int rdiv,
int fdiv, int pdiv,
int rfrq, int pfrq)
{
int dfrq;
struct drm_radeon_private *dev_priv = dev->dev_private;
int dfrq;
if (rdiv < 2 || fdiv < 4) {
return 0;
}
dfrq = rfrq / rdiv;
if (dfrq < 2000 || dfrq > 3300) {
return 0;
}
if (pfrq < 125000 || pfrq > 250000) {
return 0;
}
return 1;
if (rdiv < 2 || fdiv < 4) {
return 0;
}
dfrq = rfrq / rdiv;
if (dfrq < 2000 || dfrq > 3300) {
return 0;
}
if (pfrq < dev_priv->properties.pll_min_pll_freq ||
pfrq > dev_priv->properties.pll_max_pll_freq) {
return 0;
}
return 1;
}
static void radeon_pll1_compute(struct drm_crtc *crtc,
@ -424,7 +427,7 @@ static void radeon_pll1_compute(struct drm_crtc *crtc,
struct drm_radeon_private *dev_priv = crtc->dev->dev_private;
struct radeon_state *state = &dev_priv->driver_state;
int clock = mode->clock;
int rfrq = dev_priv->properties->pll_reference_freq;
int rfrq = dev_priv->properties.pll_reference_freq;
int pdiv = 1;
int pdiv_id = 0;
int rdiv_best = 2;
@ -441,11 +444,11 @@ static void radeon_pll1_compute(struct drm_crtc *crtc,
int diff_cpfrq = 350000;
/* clamp frequency into pll [min; max] frequency range */
if (clock > dev_priv->properties->pll_max_pll_freq) {
clock = dev_priv->properties->pll_max_pll_freq;
if (clock > dev_priv->properties.pll_max_pll_freq) {
clock = dev_priv->properties.pll_max_pll_freq;
}
if ((clock * 12) < dev_priv->properties->pll_min_pll_freq) {
clock = dev_priv->properties->pll_min_pll_freq / 12;
if ((clock * 12) < dev_priv->properties.pll_min_pll_freq) {
clock = dev_priv->properties.pll_min_pll_freq / 12;
}
/* maximize pll_ref_div while staying in boundary and minimizing
@ -457,8 +460,8 @@ static void radeon_pll1_compute(struct drm_crtc *crtc,
tfrq = clock * post_div->divider;
for (fdiv = 1023; fdiv >= 4; fdiv--) {
rdiv = (fdiv * rfrq) / tfrq;
if (radeon_pll1_constraint(clock, rdiv, fdiv,
pdiv, rfrq, tfrq)) {
if (radeon_pll1_constraint(crtc->dev, clock, rdiv,
fdiv, pdiv, rfrq, tfrq)) {
pfrq = (fdiv * rfrq) / rdiv;
diff_cpfrq = pfrq - tfrq;
if ((diff_cpfrq >= 0 &&

View file

@ -203,15 +203,35 @@ int radeon_ms_driver_load(struct drm_device *dev, unsigned long flags)
radeon_ms_driver_unload(dev);
return ret;
}
ret = radeon_ms_outputs_from_properties(dev);
if (ret != 0) {
ret = radeon_ms_outputs_from_rom(dev);
if (ret < 0) {
radeon_ms_driver_unload(dev);
return ret;
} else if (!ret) {
ret = radeon_ms_outputs_from_properties(dev);
if (ret < 0) {
radeon_ms_driver_unload(dev);
return ret;
} else if (ret == 0) {
DRM_INFO("[radeon_ms] no outputs !\n");
}
} else {
DRM_INFO("[radeon_ms] added %d outputs from rom.\n", ret);
}
ret = radeon_ms_connectors_from_properties(dev);
if (ret != 0) {
ret = radeon_ms_connectors_from_rom(dev);
if (ret < 0) {
radeon_ms_driver_unload(dev);
return ret;
} else if (!ret) {
ret = radeon_ms_connectors_from_properties(dev);
if (ret < 0) {
radeon_ms_driver_unload(dev);
return ret;
} else if (!ret) {
DRM_INFO("[radeon_ms] no connectors !\n");
}
} else {
DRM_INFO("[radeon_ms] added %d connectors from rom.\n", ret);
}
radeon_ms_outputs_save(dev, &dev_priv->load_state);
drm_initial_config(dev, false);

View file

@ -29,87 +29,6 @@
#include "drm.h"
#include "radeon_ms.h"
static struct radeon_ms_output radeon_ms_dac1 = {
OUTPUT_DAC1,
NULL,
NULL,
radeon_ms_dac1_initialize,
radeon_ms_dac1_detect,
radeon_ms_dac1_dpms,
radeon_ms_dac1_get_modes,
radeon_ms_dac1_mode_fixup,
radeon_ms_dac1_mode_set,
radeon_ms_dac1_restore,
radeon_ms_dac1_save
};
static struct radeon_ms_output radeon_ms_dac2 = {
OUTPUT_DAC2,
NULL,
NULL,
radeon_ms_dac2_initialize,
radeon_ms_dac2_detect,
radeon_ms_dac2_dpms,
radeon_ms_dac2_get_modes,
radeon_ms_dac2_mode_fixup,
radeon_ms_dac2_mode_set,
radeon_ms_dac2_restore,
radeon_ms_dac2_save
};
static struct radeon_ms_connector radeon_ms_vga = {
NULL, NULL, NULL, CONNECTOR_VGA, MT_NONE, 0, GPIO_DDC1,
{
0, -1, -1, -1, -1, -1, -1, -1
},
"VGA"
};
static struct radeon_ms_connector radeon_ms_dvi_i_2 = {
NULL, NULL, NULL, CONNECTOR_DVI_I, MT_NONE, 0, GPIO_DDC2,
{
1, -1, -1, -1, -1, -1, -1, -1
},
"DVI-I"
};
static struct radeon_ms_properties properties[] = {
/* default only one VGA connector */
{
0, 0, 27000, 25000, 200000, 1, 1, 1, 1,
{
&radeon_ms_dac1, NULL, NULL, NULL, NULL, NULL, NULL,
NULL
},
{
&radeon_ms_vga, NULL, NULL, NULL, NULL, NULL, NULL,
NULL
}
},
{
0x1043, 0x176, 27000, 25000, 200000, 1, 1, 1, 1,
{
&radeon_ms_dac1, &radeon_ms_dac2, NULL, NULL, NULL,
NULL, NULL, NULL
},
{
&radeon_ms_vga, &radeon_ms_dvi_i_2, NULL, NULL, NULL,
NULL, NULL, NULL
}
},
{
0x1002, 0x4150, 27000, 25000, 200000, 1, 1, 1, 1,
{
&radeon_ms_dac1, &radeon_ms_dac2, NULL, NULL, NULL,
NULL, NULL, NULL
},
{
&radeon_ms_vga, &radeon_ms_dvi_i_2, NULL, NULL, NULL,
NULL, NULL, NULL
}
},
};
extern const uint32_t radeon_cp_microcode[];
extern const uint32_t r200_cp_microcode[];
extern const uint32_t r300_cp_microcode[];
@ -159,7 +78,7 @@ static void r300_flush_cache(struct drm_device *dev)
int radeon_ms_family_init(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
int i;
int ret;
dev_priv->microcode = radeon_cp_microcode;
dev_priv->irq_emit = radeon_ms_irq_emit;
@ -213,17 +132,10 @@ int radeon_ms_family_init(struct drm_device *dev)
DRM_ERROR("Unknown radeon bus type, aborting\n");
return -EINVAL;
}
dev_priv->properties = NULL;
for (i = 1; i < sizeof(properties)/sizeof(properties[0]); i++) {
if (dev->pdev->subsystem_vendor == properties[i].subvendor &&
dev->pdev->subsystem_device == properties[i].subdevice) {
DRM_INFO("[radeon_ms] found properties for 0x%04X:0x%04X\n",
properties[i].subvendor, properties[i].subdevice);
dev_priv->properties = &properties[i];
}
ret = radeon_ms_rom_init(dev);
if (ret) {
return ret;
}
if (dev_priv->properties == NULL) {
dev_priv->properties = &properties[0];
}
return 0;
ret = radeon_ms_properties_init(dev);
return ret;
}

View file

@ -66,6 +66,22 @@ static int get_clock(void *data)
v = 0;
}
break;
case GPIO_MONID:
v = MMIO_R(GPIO_MONID);
if ((GPIO_MONID__GPIO_MONID_1_INPUT & v)) {
v = 1;
} else {
v = 0;
}
break;
case GPIO_CRT2_DDC:
v = MMIO_R(GPIO_CRT2_DDC);
if ((GPIO_CRT2_DDC__CRT2_DDC_CLK_INPUT & v)) {
v = 1;
} else {
v = 0;
}
break;
default:
v = 0;
break;
@ -112,6 +128,22 @@ static int get_data(void *data)
v = 0;
}
break;
case GPIO_MONID:
v = MMIO_R(GPIO_MONID);
if ((GPIO_MONID__GPIO_MONID_0_INPUT & v)) {
v = 1;
} else {
v = 0;
}
break;
case GPIO_CRT2_DDC:
v = MMIO_R(GPIO_CRT2_DDC);
if ((GPIO_CRT2_DDC__CRT2_DDC_DATA_INPUT & v)) {
v = 1;
} else {
v = 0;
}
break;
default:
v = 0;
break;
@ -157,6 +189,18 @@ static void set_clock(void *i2c_priv, int clock)
v |= GPIO_DDC2__DDC2_CLK_OUT_EN;
}
break;
case GPIO_MONID:
v &= ~GPIO_MONID__GPIO_MONID_1_OUT_EN;
if (!clock) {
v |= GPIO_MONID__GPIO_MONID_1_OUT_EN;
}
break;
case GPIO_CRT2_DDC:
v &= ~GPIO_CRT2_DDC__CRT2_DDC_CLK_OUT_EN;
if (!clock) {
v |= GPIO_CRT2_DDC__CRT2_DDC_CLK_OUT_EN;
}
break;
default:
return;
}
@ -201,6 +245,18 @@ static void set_data(void *i2c_priv, int data)
v |= GPIO_DDC2__DDC2_DATA_OUT_EN;
}
break;
case GPIO_MONID:
v &= ~GPIO_MONID__GPIO_MONID_0_OUT_EN;
if (!data) {
v |= GPIO_MONID__GPIO_MONID_0_OUT_EN;
}
break;
case GPIO_CRT2_DDC:
v &= ~GPIO_CRT2_DDC__CRT2_DDC_DATA_OUT_EN;
if (!data) {
v |= GPIO_CRT2_DDC__CRT2_DDC_DATA_OUT_EN;
}
break;
default:
return;
}
@ -251,11 +307,12 @@ struct radeon_ms_i2c *radeon_ms_i2c_create(struct drm_device *dev,
ret = i2c_bit_add_bus(&i2c->adapter);
if(ret) {
DRM_INFO("[radeon_ms] failed to register I2C '%s' bus\n",
i2c->adapter.name);
DRM_INFO("[radeon_ms] failed to register I2C '%s' bus (0x%X)\n",
i2c->adapter.name, reg);
goto out_free;
}
DRM_INFO("[radeon_ms] registered I2C '%s' bus\n", i2c->adapter.name);
DRM_INFO("[radeon_ms] registered I2C '%s' bus (0x%X)\n",
i2c->adapter.name, reg);
return i2c;
out_free:

View file

@ -189,7 +189,7 @@ static void radeon_ms_output_cleanup(struct drm_output *output)
output->driver_private = NULL;
}
static const struct drm_output_funcs radeon_ms_output_funcs = {
const struct drm_output_funcs radeon_ms_output_funcs = {
.dpms = radeon_ms_output_dpms,
.save = NULL,
.restore = NULL,
@ -233,11 +233,11 @@ int radeon_ms_connectors_from_properties(struct drm_device *dev)
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_ms_connector *connector = NULL;
struct drm_output *output = NULL;
int i = 0;
int i = 0, c = 0;
radeon_ms_connectors_destroy(dev);
for (i = 0; i < RADEON_MAX_CONNECTORS; i++) {
if (dev_priv->properties->connectors[i]) {
if (dev_priv->properties.connectors[i]) {
connector =
drm_alloc(sizeof(struct radeon_ms_connector),
DRM_MEM_DRIVER);
@ -245,11 +245,11 @@ int radeon_ms_connectors_from_properties(struct drm_device *dev)
radeon_ms_connectors_destroy(dev);
return -ENOMEM;
}
memcpy(connector,
dev_priv->properties->connectors[i],
sizeof(struct radeon_ms_connector));
connector->i2c = radeon_ms_i2c_create(dev,
connector->i2c_reg, connector->name);
memcpy(connector, dev_priv->properties.connectors[i],
sizeof(struct radeon_ms_connector));
connector->i2c =
radeon_ms_i2c_create(dev, connector->i2c_reg,
connector->name);
if (connector->i2c == NULL) {
radeon_ms_connectors_destroy(dev);
return -ENOMEM;
@ -264,9 +264,20 @@ int radeon_ms_connectors_from_properties(struct drm_device *dev)
connector->output = output;
output->driver_private = connector;
output->possible_crtcs = 0x3;
dev_priv->connectors[i] = connector;
dev_priv->connectors[c++] = connector;
}
}
return c;
}
int radeon_ms_connectors_from_rom(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
switch (dev_priv->rom.type) {
case ROM_COMBIOS:
return radeon_ms_connectors_from_combios(dev);
}
return 0;
}
@ -289,24 +300,37 @@ int radeon_ms_outputs_from_properties(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
int i = 0;
int c = 0;
radeon_ms_outputs_destroy(dev);
for (i = 0; i < RADEON_MAX_OUTPUTS; i++) {
if (dev_priv->properties->outputs[i]) {
if (dev_priv->properties.outputs[i]) {
dev_priv->outputs[i] =
drm_alloc(sizeof(struct radeon_ms_output),
DRM_MEM_DRIVER);
DRM_MEM_DRIVER);
if (dev_priv->outputs[i] == NULL) {
radeon_ms_outputs_destroy(dev);
return -ENOMEM;
}
memcpy(dev_priv->outputs[i],
dev_priv->properties->outputs[i],
sizeof(struct radeon_ms_output));
dev_priv->properties.outputs[i],
sizeof(struct radeon_ms_output));
dev_priv->outputs[i]->dev = dev;
dev_priv->outputs[i]->initialize(dev_priv->outputs[i]);
c++;
}
}
return c;
}
int radeon_ms_outputs_from_rom(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
switch (dev_priv->rom.type) {
case ROM_COMBIOS:
return radeon_ms_outputs_from_combios(dev);
}
return 0;
}

View file

@ -0,0 +1,121 @@
/*
* 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:
* Jerome Glisse <glisse@freedesktop.org>
*/
#include "drmP.h"
#include "drm.h"
#include "radeon_ms.h"
struct radeon_ms_output radeon_ms_dac1 = {
OUTPUT_DAC1,
NULL,
NULL,
radeon_ms_dac1_initialize,
radeon_ms_dac1_detect,
radeon_ms_dac1_dpms,
radeon_ms_dac1_get_modes,
radeon_ms_dac1_mode_fixup,
radeon_ms_dac1_mode_set,
radeon_ms_dac1_restore,
radeon_ms_dac1_save
};
struct radeon_ms_output radeon_ms_dac2 = {
OUTPUT_DAC2,
NULL,
NULL,
radeon_ms_dac2_initialize,
radeon_ms_dac2_detect,
radeon_ms_dac2_dpms,
radeon_ms_dac2_get_modes,
radeon_ms_dac2_mode_fixup,
radeon_ms_dac2_mode_set,
radeon_ms_dac2_restore,
radeon_ms_dac2_save
};
struct radeon_ms_connector radeon_ms_vga = {
NULL, NULL, NULL, ConnectorVGA, MT_NONE, 0, GPIO_DDC1,
{
0, -1, -1, -1, -1, -1, -1, -1
}
};
struct radeon_ms_connector radeon_ms_dvi_i_2 = {
NULL, NULL, NULL, ConnectorDVII, MT_NONE, 0, GPIO_DDC2,
{
1, -1, -1, -1, -1, -1, -1, -1
}
};
struct radeon_ms_properties properties[] = {
/* default only one VGA connector */
{
0, 0, 27000, 12, 25000, 200000, 1, 1, 1, 1,
{
&radeon_ms_dac1, NULL, NULL, NULL, NULL, NULL, NULL,
NULL
},
{
&radeon_ms_vga, NULL, NULL, NULL, NULL, NULL, NULL,
NULL
}
}
};
int radeon_ms_properties_init(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
int i, ret;
for (i = 1; i < sizeof(properties)/sizeof(properties[0]); i++) {
if (dev->pdev->subsystem_vendor == properties[i].subvendor &&
dev->pdev->subsystem_device == properties[i].subdevice) {
DRM_INFO("[radeon_ms] found properties for "
"0x%04X:0x%04X\n", properties[i].subvendor,
properties[i].subdevice);
memcpy(&dev_priv->properties, &properties[i],
sizeof(struct radeon_ms_properties));
}
}
if (dev_priv->properties.subvendor == 0) {
ret = radeon_ms_rom_get_properties(dev);
if (ret < 0) {
return ret;
}
if (!ret) {
memcpy(&dev_priv->properties, &properties[0],
sizeof(struct radeon_ms_properties));
} else {
dev_priv->properties.pll_dummy_reads = 1;
dev_priv->properties.pll_delay = 1;
dev_priv->properties.pll_r300_errata = 1;
}
dev_priv->properties.subvendor = dev->pdev->subsystem_vendor;
dev_priv->properties.subdevice = dev->pdev->subsystem_device;
}
return 0;
}

View file

@ -0,0 +1,50 @@
/*
* 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:
* Jerome Glisse <glisse@freedesktop.org>
*/
#ifndef __RADEON_MS_PROPERTIES_H__
#define __RADEON_MS_PROPERTIES_H__
#define RADEON_PAGE_SIZE 4096
#define RADEON_MAX_CONNECTORS 8
#define RADEON_MAX_OUTPUTS 8
struct radeon_ms_properties {
uint16_t subvendor;
uint16_t subdevice;
int16_t pll_reference_freq;
int16_t pll_reference_div;
int32_t pll_min_pll_freq;
int32_t pll_max_pll_freq;
char pll_use_bios;
char pll_dummy_reads;
char pll_delay;
char pll_r300_errata;
struct radeon_ms_output *outputs[RADEON_MAX_OUTPUTS];
struct radeon_ms_connector *connectors[RADEON_MAX_CONNECTORS];
};
#endif

View file

@ -827,6 +827,32 @@
#define GPIO_DDC2__SW_CAN_USE_DVI_I2C 0x00100000
#define GPIO_DDC2__SW_DONE_USING_DVI_I2C 0x00200000
#define GPIO_DDC2__HW_USING_DVI_I2C 0x00400000
#define GPIO_DVI_DDC 0x00000064
#define GPIO_DVI_DDC__DVI_DDC_DATA_OUTPUT 0x00000001
#define GPIO_DVI_DDC__DVI_DCC_DATA_OUTPUT 0x00000001
#define GPIO_DVI_DDC__DVI_DDC_CLK_OUTPUT 0x00000002
#define GPIO_DVI_DDC__DVI_DDC_DATA_INPUT 0x00000100
#define GPIO_DVI_DDC__DVI_DDC_CLK_INPUT 0x00000200
#define GPIO_DVI_DDC__DVI_DDC_DATA_OUT_EN 0x00010000
#define GPIO_DVI_DDC__DVI_DDC_CLK_OUT_EN 0x00020000
#define GPIO_DVI_DDC__SW_WANTS_TO_USE_DVI_I2C 0x00100000
#define GPIO_DVI_DDC__SW_CAN_USE_DVI_I2C 0x00100000
#define GPIO_DVI_DDC__SW_DONE_USING_DVI_I2C 0x00200000
#define GPIO_DVI_DDC__HW_USING_DVI_I2C 0x00400000
#define GPIO_MONID 0x00000068
#define GPIO_MONID__GPIO_MONID_0_OUTPUT 0x00000001
#define GPIO_MONID__GPIO_MONID_1_OUTPUT 0x00000002
#define GPIO_MONID__GPIO_MONID_0_INPUT 0x00000100
#define GPIO_MONID__GPIO_MONID_1_INPUT 0x00000200
#define GPIO_MONID__GPIO_MONID_0_OUT_EN 0x00010000
#define GPIO_MONID__GPIO_MONID_1_OUT_EN 0x00020000
#define GPIO_CRT2_DDC 0x0000006C
#define GPIO_CRT2_DDC__CRT2_DDC_DATA_OUTPUT 0x00000001
#define GPIO_CRT2_DDC__CRT2_DDC_CLK_OUTPUT 0x00000002
#define GPIO_CRT2_DDC__CRT2_DDC_DATA_INPUT 0x00000100
#define GPIO_CRT2_DDC__CRT2_DDC_CLK_INPUT 0x00000200
#define GPIO_CRT2_DDC__CRT2_DDC_DATA_OUT_EN 0x00010000
#define GPIO_CRT2_DDC__CRT2_DDC_CLK_OUT_EN 0x00020000
#define CLOCK_CNTL_INDEX 0x00000008
#define CLOCK_CNTL_INDEX__PLL_ADDR__MASK 0x0000001F
#define CLOCK_CNTL_INDEX__PLL_ADDR__SHIFT 0

View file

@ -0,0 +1,91 @@
/*
* 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:
* Jerome Glisse <glisse@freedesktop.org>
*/
#include "radeon_ms.h"
int radeon_ms_rom_get_properties(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
switch (dev_priv->rom.type) {
case ROM_COMBIOS:
return radeon_ms_combios_get_properties(dev);
}
return 0;
}
int radeon_ms_rom_init(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_ms_rom *rom = &dev_priv->rom;
void *rom_mapped;
char atomstr[5] = {0, 0, 0, 0, 0};
uint16_t *offset;
dev_priv->rom.type = ROM_UNKNOWN;
/* copy rom if any */
rom_mapped = pci_map_rom_copy(dev->pdev, &rom->rom_size);
if (rom->rom_size) {
rom->rom_image = drm_alloc(rom->rom_size, DRM_MEM_DRIVER);
if (rom->rom_image == NULL) {
return -1;
}
memcpy(rom->rom_image, rom_mapped, rom->rom_size);
DRM_INFO("[radeon_ms] ROM %d bytes copied\n", rom->rom_size);
} else {
DRM_INFO("[radeon_ms] no ROM\n");
return 0;
}
pci_unmap_rom(dev->pdev, rom_mapped);
if (rom->rom_image[0] != 0x55 || rom->rom_image[1] != 0xaa) {
DRM_INFO("[radeon_ms] no ROM\n");
DRM_INFO("[radeon_ms] ROM signature 0x55 0xaa missing\n");
return 0;
}
offset = (uint16_t *)&rom->rom_image[ROM_HEADER];
memcpy(atomstr, &rom->rom_image[*offset + 4], 4);
if (!strcpy(atomstr, "ATOM") || !strcpy(atomstr, "MOTA")) {
DRM_INFO("[radeon_ms] ATOMBIOS ROM detected\n");
return 0;
} else {
struct combios_header **header;
header = &rom->rom.combios_header;
if ((*offset + sizeof(struct combios_header)) > rom->rom_size) {
DRM_INFO("[radeon_ms] wrong COMBIOS header offset\n");
return -1;
}
dev_priv->rom.type = ROM_COMBIOS;
*header = (struct combios_header *)&rom->rom_image[*offset];
DRM_INFO("[radeon_ms] COMBIOS type : %d\n",
(*header)->ucTypeDefinition);
DRM_INFO("[radeon_ms] COMBIOS OEM ID: %02x %02x\n",
(*header)->ucOemID1, (*header)->ucOemID2);
}
return 0;
}

View file

@ -0,0 +1,51 @@
/*
* 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:
* Jerome Glisse <glisse@freedesktop.org>
*/
#ifndef __RADEON_MS_ROM_H__
#define __RADEON_MS_ROM_H__
#include "radeon_ms_combios.h"
enum radeon_rom_type {
ROM_COMBIOS,
ROM_ATOMBIOS,
ROM_UNKNOWN
};
union radeon_ms_rom_type {
struct combios_header *combios_header;
};
struct radeon_ms_rom {
uint8_t type;
size_t rom_size;
uint8_t *rom_image;
union radeon_ms_rom_type rom;
};
#endif