summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <glisse@freedesktop.org>2008-01-15 14:05:25 +0100
committerJohn Doe <glisse@freedesktop.org>2008-01-15 14:17:05 +0100
commitf1f934c8c97d6664fb5e1920a41154c09cc7f293 (patch)
treebfa707e2d430643b4f5ab7a94a7f59508ae60127
parente6fc47129ffe972bbee1c08fd822a8c171f21322 (diff)
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.
-rw-r--r--linux-core/Makefile.kernel3
l---------linux-core/radeon_ms_combios.c1
l---------linux-core/radeon_ms_combios.h1
l---------linux-core/radeon_ms_properties.c1
l---------linux-core/radeon_ms_properties.h1
l---------linux-core/radeon_ms_rom.c1
l---------linux-core/radeon_ms_rom.h1
-rw-r--r--shared-core/radeon_ms.h44
-rw-r--r--shared-core/radeon_ms_combios.c396
-rw-r--r--shared-core/radeon_ms_combios.h385
-rw-r--r--shared-core/radeon_ms_crtc.c45
-rw-r--r--shared-core/radeon_ms_drm.c28
-rw-r--r--shared-core/radeon_ms_family.c100
-rw-r--r--shared-core/radeon_ms_i2c.c63
-rw-r--r--shared-core/radeon_ms_output.c50
-rw-r--r--shared-core/radeon_ms_properties.c121
-rw-r--r--shared-core/radeon_ms_properties.h50
-rw-r--r--shared-core/radeon_ms_reg.h26
-rw-r--r--shared-core/radeon_ms_rom.c91
-rw-r--r--shared-core/radeon_ms_rom.h51
20 files changed, 1301 insertions, 158 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index 7ef504ad..b4fdcf6b 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -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
diff --git a/linux-core/radeon_ms_combios.c b/linux-core/radeon_ms_combios.c
new file mode 120000
index 00000000..d7b99958
--- /dev/null
+++ b/linux-core/radeon_ms_combios.c
@@ -0,0 +1 @@
+../shared-core/radeon_ms_combios.c \ No newline at end of file
diff --git a/linux-core/radeon_ms_combios.h b/linux-core/radeon_ms_combios.h
new file mode 120000
index 00000000..5b19c708
--- /dev/null
+++ b/linux-core/radeon_ms_combios.h
@@ -0,0 +1 @@
+../shared-core/radeon_ms_combios.h \ No newline at end of file
diff --git a/linux-core/radeon_ms_properties.c b/linux-core/radeon_ms_properties.c
new file mode 120000
index 00000000..e2e0dc0b
--- /dev/null
+++ b/linux-core/radeon_ms_properties.c
@@ -0,0 +1 @@
+../shared-core/radeon_ms_properties.c \ No newline at end of file
diff --git a/linux-core/radeon_ms_properties.h b/linux-core/radeon_ms_properties.h
new file mode 120000
index 00000000..59783e89
--- /dev/null
+++ b/linux-core/radeon_ms_properties.h
@@ -0,0 +1 @@
+../shared-core/radeon_ms_properties.h \ No newline at end of file
diff --git a/linux-core/radeon_ms_rom.c b/linux-core/radeon_ms_rom.c
new file mode 120000
index 00000000..80f5f606
--- /dev/null
+++ b/linux-core/radeon_ms_rom.c
@@ -0,0 +1 @@
+../shared-core/radeon_ms_rom.c \ No newline at end of file
diff --git a/linux-core/radeon_ms_rom.h b/linux-core/radeon_ms_rom.h
new file mode 120000
index 00000000..f20e42be
--- /dev/null
+++ b/linux-core/radeon_ms_rom.h
@@ -0,0 +1 @@
+../shared-core/radeon_ms_rom.h \ No newline at end of file
diff --git a/shared-core/radeon_ms.h b/shared-core/radeon_ms.h
index ee795f3a..a784882b 100644
--- a/shared-core/radeon_ms.h
+++ b/shared-core/radeon_ms.h
@@ -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);
}
diff --git a/shared-core/radeon_ms_combios.c b/shared-core/radeon_ms_combios.c
new file mode 100644
index 00000000..04a33699
--- /dev/null
+++ b/shared-core/radeon_ms_combios.c
@@ -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;
+}
diff --git a/shared-core/radeon_ms_combios.h b/shared-core/radeon_ms_combios.h
new file mode 100644
index 00000000..fbceadf2
--- /dev/null
+++ b/shared-core/radeon_ms_combios.h
@@ -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
diff --git a/shared-core/radeon_ms_crtc.c b/shared-core/radeon_ms_crtc.c
index fe89e5e4..0da5a5a4 100644
--- a/shared-core/radeon_ms_crtc.c
+++ b/shared-core/radeon_ms_crtc.c
@@ -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;
-
- 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;
+ 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 < 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 &&
diff --git a/shared-core/radeon_ms_drm.c b/shared-core/radeon_ms_drm.c
index 8d0481e1..91ca4a32 100644
--- a/shared-core/radeon_ms_drm.c
+++ b/shared-core/radeon_ms_drm.c
@@ -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);
diff --git a/shared-core/radeon_ms_family.c b/shared-core/radeon_ms_family.c
index 779595d6..b70dca20 100644
--- a/shared-core/radeon_ms_family.c
+++ b/shared-core/radeon_ms_family.c
@@ -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];
- }
- }
- if (dev_priv->properties == NULL) {
- dev_priv->properties = &properties[0];
+ ret = radeon_ms_rom_init(dev);
+ if (ret) {
+ return ret;
}
- return 0;
+ ret = radeon_ms_properties_init(dev);
+ return ret;
}
diff --git a/shared-core/radeon_ms_i2c.c b/shared-core/radeon_ms_i2c.c
index 1801c496..f4468c1e 100644
--- a/shared-core/radeon_ms_i2c.c
+++ b/shared-core/radeon_ms_i2c.c
@@ -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:
diff --git a/shared-core/radeon_ms_output.c b/shared-core/radeon_ms_output.c
index 35e5c376..18806324 100644
--- a/shared-core/radeon_ms_output.c
+++ b/shared-core/radeon_ms_output.c
@@ -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;
}
diff --git a/shared-core/radeon_ms_properties.c b/shared-core/radeon_ms_properties.c
new file mode 100644
index 00000000..393f496f
--- /dev/null
+++ b/shared-core/radeon_ms_properties.c
@@ -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;
+}
diff --git a/shared-core/radeon_ms_properties.h b/shared-core/radeon_ms_properties.h
new file mode 100644
index 00000000..a02a84d5
--- /dev/null
+++ b/shared-core/radeon_ms_properties.h
@@ -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
diff --git a/shared-core/radeon_ms_reg.h b/shared-core/radeon_ms_reg.h
index d450280c..56963c63 100644
--- a/shared-core/radeon_ms_reg.h
+++ b/shared-core/radeon_ms_reg.h
@@ -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
diff --git a/shared-core/radeon_ms_rom.c b/shared-core/radeon_ms_rom.c
new file mode 100644
index 00000000..5054a390
--- /dev/null
+++ b/shared-core/radeon_ms_rom.c
@@ -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;
+}
diff --git a/shared-core/radeon_ms_rom.h b/shared-core/radeon_ms_rom.h
new file mode 100644
index 00000000..36a54cbb
--- /dev/null
+++ b/shared-core/radeon_ms_rom.h
@@ -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
+