This is required for the NB_MISC regs on rs780/rs880 which
means HDMI/DVI/DP ports using PCIEPHY won't work without
it. It might also help with s/r (asic init) issues on other
atombios cards.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=28774
and similar issues reported by Alberto Milone.

Signed-off-by: Alex Deucher <alexdeuc...@gmail.com>
---
 drivers/gpu/drm/radeon/atom.c          |    5 +--
 drivers/gpu/drm/radeon/atom.h          |    2 +
 drivers/gpu/drm/radeon/radeon.h        |   25 +++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_device.c |   34 ++++++++++++++++++++++++++++++++
 4 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 1d56983..b2e3314 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -108,12 +108,11 @@ static uint32_t atom_iio_execute(struct atom_context 
*ctx, int base,
                        base++;
                        break;
                case ATOM_IIO_READ:
-                       temp = ctx->card->reg_read(ctx->card, CU16(base + 1));
+                       temp = ctx->card->ioreg_read(ctx->card, CU16(base + 1));
                        base += 3;
                        break;
                case ATOM_IIO_WRITE:
-                       (void)ctx->card->reg_read(ctx->card, CU16(base + 1));
-                       ctx->card->reg_write(ctx->card, CU16(base + 1), temp);
+                       ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
                        base += 3;
                        break;
                case ATOM_IIO_CLEAR:
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
index cd1b64a..a589a55 100644
--- a/drivers/gpu/drm/radeon/atom.h
+++ b/drivers/gpu/drm/radeon/atom.h
@@ -113,6 +113,8 @@ struct card_info {
        struct drm_device *dev;
        void (* reg_write)(struct card_info *, uint32_t, uint32_t);   /*  
filled by driver */
         uint32_t (* reg_read)(struct card_info *, uint32_t);          /*  
filled by driver */
+       void (* ioreg_write)(struct card_info *, uint32_t, uint32_t);   /*  
filled by driver */
+        uint32_t (* ioreg_read)(struct card_info *, uint32_t);          /*  
filled by driver */
        void (* mc_write)(struct card_info *, uint32_t, uint32_t);   /*  filled 
by driver */
         uint32_t (* mc_read)(struct card_info *, uint32_t);          /*  
filled by driver */
        void (* pll_write)(struct card_info *, uint32_t, uint32_t);   /*  
filled by driver */
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 8e1d44c..35f0800 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1030,6 +1030,9 @@ struct radeon_device {
        uint32_t                        pcie_reg_mask;
        radeon_rreg_t                   pciep_rreg;
        radeon_wreg_t                   pciep_wreg;
+       /* io port */
+       void __iomem                    *rio_mem;
+       resource_size_t                 rio_mem_size;
        struct radeon_clock             clock;
        struct radeon_mc                mc;
        struct radeon_gart              gart;
@@ -1111,6 +1114,26 @@ static inline void r100_mm_wreg(struct radeon_device 
*rdev, uint32_t reg, uint32
        }
 }
 
+static inline u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
+{
+       if (reg < rdev->rio_mem_size)
+               return ioread32(rdev->rio_mem + reg);
+       else {
+               iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+               return ioread32(rdev->rio_mem + RADEON_MM_DATA);
+       }
+}
+
+static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
+{
+       if (reg < rdev->rio_mem_size)
+               iowrite32(v, rdev->rio_mem + reg);
+       else {
+               iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
+               iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
+       }
+}
+
 /*
  * Cast helper
  */
@@ -1149,6 +1172,8 @@ static inline void r100_mm_wreg(struct radeon_device 
*rdev, uint32_t reg, uint32
                WREG32_PLL(reg, tmp_);                          \
        } while (0)
 #define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", 
r100_mm_rreg((rdev), (reg)))
+#define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
+#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
 
 /*
  * Indirect registers accessor
diff --git a/drivers/gpu/drm/radeon/radeon_device.c 
b/drivers/gpu/drm/radeon/radeon_device.c
index 5f31731..fa85a34 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -415,6 +415,22 @@ static uint32_t cail_reg_read(struct card_info *info, 
uint32_t reg)
        return r;
 }
 
+static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t 
val)
+{
+       struct radeon_device *rdev = info->dev->dev_private;
+
+       WREG32_IO(reg*4, val);
+}
+
+static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
+{
+       struct radeon_device *rdev = info->dev->dev_private;
+       uint32_t r;
+
+       r = RREG32_IO(reg*4);
+       return r;
+}
+
 int radeon_atombios_init(struct radeon_device *rdev)
 {
        struct card_info *atom_card_info =
@@ -427,6 +443,9 @@ int radeon_atombios_init(struct radeon_device *rdev)
        atom_card_info->dev = rdev->ddev;
        atom_card_info->reg_read = cail_reg_read;
        atom_card_info->reg_write = cail_reg_write;
+       /* needed for iio ops */
+       atom_card_info->ioreg_read = cail_ioreg_read;
+       atom_card_info->ioreg_write = cail_ioreg_write;
        atom_card_info->mc_read = cail_mc_read;
        atom_card_info->mc_write = cail_mc_write;
        atom_card_info->pll_read = cail_pll_read;
@@ -659,6 +678,19 @@ int radeon_device_init(struct radeon_device *rdev,
        DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
        DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
 
+       /* io port mapping */
+       if (rdev->family >= CHIP_RV770) {
+               rdev->rio_mem_size = pci_resource_len(rdev->pdev, 4);
+               rdev->rio_mem = pci_iomap(rdev->pdev, 4, rdev->rio_mem_size);
+       } else {
+               rdev->rio_mem_size = pci_resource_len(rdev->pdev, 1);
+               rdev->rio_mem = pci_iomap(rdev->pdev, 1, rdev->rio_mem_size);
+       }
+       if (rdev->rio_mem == NULL) {
+               iounmap(rdev->rmmio);
+               return -EIO;
+       }
+
        /* if we have > 1 VGA cards, then disable the radeon VGA resources */
        /* this will fail for cards that aren't VGA class devices, just
         * ignore it */
@@ -701,6 +733,8 @@ void radeon_device_fini(struct radeon_device *rdev)
        destroy_workqueue(rdev->wq);
        vga_switcheroo_unregister_client(rdev->pdev);
        vga_client_register(rdev->pdev, NULL, NULL, NULL);
+       pci_iounmap(rdev->pdev, rdev->rio_mem);
+       rdev->rio_mem = NULL;
        iounmap(rdev->rmmio);
        rdev->rmmio = NULL;
 }
-- 
1.7.0.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to