radeon_ms: add rom parsing & adapt code
authorJerome Glisse <glisse@freedesktop.org>
Tue, 15 Jan 2008 13:05:25 +0000 (14:05 +0100)
committerJohn Doe <glisse@freedesktop.org>
Tue, 15 Jan 2008 13:17:05 +0000 (14:17 +0100)
Add rom (only combios for now) parsing and use informations
retrieve instead of hardcoded table. Shuffle code around a
bit.

20 files changed:
linux-core/Makefile.kernel
linux-core/radeon_ms_combios.c [new symlink]
linux-core/radeon_ms_combios.h [new symlink]
linux-core/radeon_ms_properties.c [new symlink]
linux-core/radeon_ms_properties.h [new symlink]
linux-core/radeon_ms_rom.c [new symlink]
linux-core/radeon_ms_rom.h [new symlink]
shared-core/radeon_ms.h
shared-core/radeon_ms_combios.c [new file with mode: 0644]
shared-core/radeon_ms_combios.h [new file with mode: 0644]
shared-core/radeon_ms_crtc.c
shared-core/radeon_ms_drm.c
shared-core/radeon_ms_family.c
shared-core/radeon_ms_i2c.c
shared-core/radeon_ms_output.c
shared-core/radeon_ms_properties.c [new file with mode: 0644]
shared-core/radeon_ms_properties.h [new file with mode: 0644]
shared-core/radeon_ms_reg.h
shared-core/radeon_ms_rom.c [new file with mode: 0644]
shared-core/radeon_ms_rom.h [new file with mode: 0644]

index 7ef504a..b4fdcf6 100644 (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
diff --git a/linux-core/radeon_ms_combios.c b/linux-core/radeon_ms_combios.c
new file mode 120000 (symlink)
index 0000000..d7b9995
--- /dev/null
@@ -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 (symlink)
index 0000000..5b19c70
--- /dev/null
@@ -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 (symlink)
index 0000000..e2e0dc0
--- /dev/null
@@ -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 (symlink)
index 0000000..59783e8
--- /dev/null
@@ -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 (symlink)
index 0000000..80f5f60
--- /dev/null
@@ -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 (symlink)
index 0000000..f20e42b
--- /dev/null
@@ -0,0 +1 @@
+../shared-core/radeon_ms_rom.h
\ No newline at end of file
index ee795f3..a784882 100644 (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."
 #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 (file)
index 0000000..04a3369
--- /dev/null
@@ -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 (file)
index 0000000..fbceadf
--- /dev/null
@@ -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
index fe89e5e..0da5a5a 100644 (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;
-
-    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 &&
index 8d0481e..91ca4a3 100644 (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);
index 779595d..b70dca2 100644 (file)
 #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;
 }
index 1801c49..f4468c1 100644 (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:
index 35e5c37..1880632 100644 (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;
 }
 
diff --git a/shared-core/radeon_ms_properties.c b/shared-core/radeon_ms_properties.c
new file mode 100644 (file)
index 0000000..393f496
--- /dev/null
@@ -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 (file)
index 0000000..a02a84d
--- /dev/null
@@ -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
index d450280..56963c6 100644 (file)
 #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 (file)
index 0000000..5054a39
--- /dev/null
@@ -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 (file)
index 0000000..36a54cb
--- /dev/null
@@ -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
+