Merge branch 'drm-fixes-3.6' of git://people.freedesktop.org/~agd5f/linux into drm...
authorDave Airlie <airlied@redhat.com>
Tue, 21 Aug 2012 23:18:49 +0000 (09:18 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 21 Aug 2012 23:18:49 +0000 (09:18 +1000)
Alex writes:

"This is the current set of radeon fixes for 3.6.  Nothing too major.

Highlights:
- fix vbios fetch on pure uefi systems
- fix vbios fetch on thunderbolt systems
- MSAA fixes
- lockup timeout fix
- modesetting fix"

* 'drm-fixes-3.6' of git://people.freedesktop.org/~agd5f/linux:
  drm/radeon/ss: use num_crtc rather than hardcoded 6
  Revert "drm/radeon: fix bo creation retry path"
  drm/radeon: split ATRM support out from the ATPX handler (v3)
  drm/radeon: convert radeon vfct code to use acpi_get_table_with_size
  ACPI: export symbol acpi_get_table_with_size
  drm/radeon: implement ACPI VFCT vbios fetch (v3)
  drm/radeon/kms: extend the Fujitsu D3003-S2 board connector quirk to cover later silicon stepping
  drm/radeon: fix checking of MSAA renderbuffers on r600-r700
  drm/radeon: allow CMASK and FMASK in the CS checker on r600-r700
  drm/radeon: init lockup timeout on ring init
  drm/radeon: avoid turning off spread spectrum for used pll

12 files changed:
drivers/acpi/acpica/tbxface.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/reg_srcs/r600

index ea4c6d5..29e51bc 100644 (file)
@@ -387,6 +387,7 @@ acpi_get_table_with_size(char *signature,
 
        return (AE_NOT_FOUND);
 }
+ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
 
 acpi_status
 acpi_get_table(char *signature,
index c6fcb5b..f4d4505 100644 (file)
@@ -444,11 +444,28 @@ union atom_enable_ss {
 static void atombios_crtc_program_ss(struct radeon_device *rdev,
                                     int enable,
                                     int pll_id,
+                                    int crtc_id,
                                     struct radeon_atom_ss *ss)
 {
+       unsigned i;
        int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
        union atom_enable_ss args;
 
+       if (!enable) {
+               for (i = 0; i < rdev->num_crtc; i++) {
+                       if (rdev->mode_info.crtcs[i] &&
+                           rdev->mode_info.crtcs[i]->enabled &&
+                           i != crtc_id &&
+                           pll_id == rdev->mode_info.crtcs[i]->pll_id) {
+                               /* one other crtc is using this pll don't turn
+                                * off spread spectrum as it might turn off
+                                * display on active crtc
+                                */
+                               return;
+                       }
+               }
+       }
+
        memset(&args, 0, sizeof(args));
 
        if (ASIC_IS_DCE5(rdev)) {
@@ -1028,7 +1045,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
                                          &ref_div, &post_div);
 
-       atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
+       atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
 
        atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
                                  encoder_mode, radeon_encoder->encoder_id, mode->clock,
@@ -1051,7 +1068,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
                        ss.step = step_size;
                }
 
-               atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
+               atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);
        }
 }
 
@@ -1572,11 +1589,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)
                                                                   ASIC_INTERNAL_SS_ON_DCPLL,
                                                                   rdev->clock.default_dispclk);
                if (ss_enabled)
-                       atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
+                       atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);
                /* XXX: DCE5, make sure voltage, dispclk is high enough */
                atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);
                if (ss_enabled)
-                       atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
+                       atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);
        }
 
 }
index 3dab49c..ab74e6b 100644 (file)
@@ -47,13 +47,17 @@ struct r600_cs_track {
        u32                     npipes;
        /* value we track */
        u32                     sq_config;
+       u32                     log_nsamples;
        u32                     nsamples;
        u32                     cb_color_base_last[8];
        struct radeon_bo        *cb_color_bo[8];
        u64                     cb_color_bo_mc[8];
-       u32                     cb_color_bo_offset[8];
-       struct radeon_bo        *cb_color_frag_bo[8]; /* unused */
-       struct radeon_bo        *cb_color_tile_bo[8]; /* unused */
+       u64                     cb_color_bo_offset[8];
+       struct radeon_bo        *cb_color_frag_bo[8];
+       u64                     cb_color_frag_offset[8];
+       struct radeon_bo        *cb_color_tile_bo[8];
+       u64                     cb_color_tile_offset[8];
+       u32                     cb_color_mask[8];
        u32                     cb_color_info[8];
        u32                     cb_color_view[8];
        u32                     cb_color_size_idx[8]; /* unused */
@@ -349,10 +353,6 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        unsigned array_mode;
        u32 format;
 
-       if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
-               dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
-               return -EINVAL;
-       }
        size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
        format = G_0280A0_FORMAT(track->cb_color_info[i]);
        if (!r600_fmt_is_valid_color(format)) {
@@ -420,7 +420,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        }
 
        /* check offset */
-       tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format);
+       tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
+             r600_fmt_get_blocksize(format) * track->nsamples;
        switch (array_mode) {
        default:
        case V_0280A0_ARRAY_LINEAR_GENERAL:
@@ -441,7 +442,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
                         * broken userspace.
                         */
                } else {
-                       dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n",
+                       dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
                                 __func__, i, array_mode,
                                 track->cb_color_bo_offset[i], tmp,
                                 radeon_bo_size(track->cb_color_bo[i]),
@@ -458,6 +459,51 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
                S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
        ib[track->cb_color_size_idx[i]] = tmp;
+
+       /* FMASK/CMASK */
+       switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
+       case V_0280A0_TILE_DISABLE:
+               break;
+       case V_0280A0_FRAG_ENABLE:
+               if (track->nsamples > 1) {
+                       uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]);
+                       /* the tile size is 8x8, but the size is in units of bits.
+                        * for bytes, do just * 8. */
+                       uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1);
+
+                       if (bytes + track->cb_color_frag_offset[i] >
+                           radeon_bo_size(track->cb_color_frag_bo[i])) {
+                               dev_warn(p->dev, "%s FMASK_TILE_MAX too large "
+                                        "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
+                                        __func__, tile_max, bytes,
+                                        track->cb_color_frag_offset[i],
+                                        radeon_bo_size(track->cb_color_frag_bo[i]));
+                               return -EINVAL;
+                       }
+               }
+               /* fall through */
+       case V_0280A0_CLEAR_ENABLE:
+       {
+               uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]);
+               /* One block = 128x128 pixels, one 8x8 tile has 4 bits..
+                * (128*128) / (8*8) / 2 = 128 bytes per block. */
+               uint32_t bytes = (block_max + 1) * 128;
+
+               if (bytes + track->cb_color_tile_offset[i] >
+                   radeon_bo_size(track->cb_color_tile_bo[i])) {
+                       dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large "
+                                "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
+                                __func__, block_max, bytes,
+                                track->cb_color_tile_offset[i],
+                                radeon_bo_size(track->cb_color_tile_bo[i]));
+                       return -EINVAL;
+               }
+               break;
+       }
+       default:
+               dev_warn(p->dev, "%s invalid tile mode\n", __func__);
+               return -EINVAL;
+       }
        return 0;
 }
 
@@ -566,7 +612,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
 
                ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
                nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
-               tmp = ntiles * bpe * 64 * nviews;
+               tmp = ntiles * bpe * 64 * nviews * track->nsamples;
                if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
                        dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
                                        array_mode,
@@ -1231,6 +1277,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                break;
        case R_028C04_PA_SC_AA_CONFIG:
                tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
+               track->log_nsamples = tmp;
                track->nsamples = 1 << tmp;
                track->cb_dirty = true;
                break;
@@ -1312,16 +1359,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
                        }
-                       ib[idx] = track->cb_color_base_last[tmp];
                        track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
+                       track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
+                       ib[idx] = track->cb_color_base_last[tmp];
                } else {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
                        }
-                       ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                        track->cb_color_frag_bo[tmp] = reloc->robj;
+                       track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8;
+                       ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               }
+               if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
+                       track->cb_dirty = true;
                }
                break;
        case R_0280C0_CB_COLOR0_TILE:
@@ -1338,16 +1390,35 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                                dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
                                return -EINVAL;
                        }
-                       ib[idx] = track->cb_color_base_last[tmp];
                        track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
+                       track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
+                       ib[idx] = track->cb_color_base_last[tmp];
                } else {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
                                return -EINVAL;
                        }
-                       ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
                        track->cb_color_tile_bo[tmp] = reloc->robj;
+                       track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8;
+                       ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
+               }
+               if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
+                       track->cb_dirty = true;
+               }
+               break;
+       case R_028100_CB_COLOR0_MASK:
+       case R_028104_CB_COLOR1_MASK:
+       case R_028108_CB_COLOR2_MASK:
+       case R_02810C_CB_COLOR3_MASK:
+       case R_028110_CB_COLOR4_MASK:
+       case R_028114_CB_COLOR5_MASK:
+       case R_028118_CB_COLOR6_MASK:
+       case R_02811C_CB_COLOR7_MASK:
+               tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
+               track->cb_color_mask[tmp] = ib[idx];
+               if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
+                       track->cb_dirty = true;
                }
                break;
        case CB_COLOR0_BASE:
@@ -1492,7 +1563,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level)
 }
 
 static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
-                             unsigned w0, unsigned h0, unsigned d0, unsigned format,
+                             unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,
                              unsigned block_align, unsigned height_align, unsigned base_align,
                              unsigned *l0_size, unsigned *mipmap_size)
 {
@@ -1520,7 +1591,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
 
                depth = r600_mip_minify(d0, i);
 
-               size = nbx * nby * blocksize;
+               size = nbx * nby * blocksize * nsamples;
                if (nfaces)
                        size *= nfaces;
                else
@@ -1672,7 +1743,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
 
                nfaces = larray - barray + 1;
        }
-       r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format,
+       r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,
                          pitch_align, height_align, base_align,
                          &l0_size, &mipmap_size);
        /* using get ib will give us the offset into the texture bo */
index fd328f4..bdb69a6 100644 (file)
 #define R_028094_CB_COLOR5_VIEW                      0x028094
 #define R_028098_CB_COLOR6_VIEW                      0x028098
 #define R_02809C_CB_COLOR7_VIEW                      0x02809C
+#define R_028100_CB_COLOR0_MASK                      0x028100
+#define   S_028100_CMASK_BLOCK_MAX(x)                  (((x) & 0xFFF) << 0)
+#define   G_028100_CMASK_BLOCK_MAX(x)                  (((x) >> 0) & 0xFFF)
+#define   C_028100_CMASK_BLOCK_MAX                     0xFFFFF000
+#define   S_028100_FMASK_TILE_MAX(x)                   (((x) & 0xFFFFF) << 12)
+#define   G_028100_FMASK_TILE_MAX(x)                   (((x) >> 12) & 0xFFFFF)
+#define   C_028100_FMASK_TILE_MAX                      0x00000FFF
+#define R_028104_CB_COLOR1_MASK                      0x028104
+#define R_028108_CB_COLOR2_MASK                      0x028108
+#define R_02810C_CB_COLOR3_MASK                      0x02810C
+#define R_028110_CB_COLOR4_MASK                      0x028110
+#define R_028114_CB_COLOR5_MASK                      0x028114
+#define R_028118_CB_COLOR6_MASK                      0x028118
+#define R_02811C_CB_COLOR7_MASK                      0x02811C
 #define CB_COLOR0_INFO                                  0x280a0
 #      define CB_FORMAT(x)                             ((x) << 2)
 #       define CB_ARRAY_MODE(x)                         ((x) << 8)
 #define   S_0280A0_TILE_MODE(x)                        (((x) & 0x3) << 18)
 #define   G_0280A0_TILE_MODE(x)                        (((x) >> 18) & 0x3)
 #define   C_0280A0_TILE_MODE                           0xFFF3FFFF
+#define     V_0280A0_TILE_DISABLE                      0
+#define     V_0280A0_CLEAR_ENABLE                      1
+#define     V_0280A0_FRAG_ENABLE                       2
 #define   S_0280A0_BLEND_CLAMP(x)                      (((x) & 0x1) << 20)
 #define   G_0280A0_BLEND_CLAMP(x)                      (((x) >> 20) & 0x1)
 #define   C_0280A0_BLEND_CLAMP                         0xFFEFFFFF
index 9930419..59a1531 100644 (file)
@@ -142,21 +142,6 @@ struct radeon_device;
 /*
  * BIOS.
  */
-#define ATRM_BIOS_PAGE 4096
-
-#if defined(CONFIG_VGA_SWITCHEROO)
-bool radeon_atrm_supported(struct pci_dev *pdev);
-int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len);
-#else
-static inline bool radeon_atrm_supported(struct pci_dev *pdev)
-{
-       return false;
-}
-
-static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){
-       return -EINVAL;
-}
-#endif
 bool radeon_get_bios(struct radeon_device *rdev);
 
 /*
index f9c21f9..d67d4f3 100644 (file)
@@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
        }
 
        /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
-       if ((dev->pdev->device == 0x9802) &&
+       if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&
            (dev->pdev->subsystem_vendor == 0x1734) &&
            (dev->pdev->subsystem_device == 0x11bd)) {
                if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
index 98724fc..2a2cf0b 100644 (file)
@@ -30,57 +30,8 @@ static struct radeon_atpx_priv {
        /* handle for device - and atpx */
        acpi_handle dhandle;
        acpi_handle atpx_handle;
-       acpi_handle atrm_handle;
 } radeon_atpx_priv;
 
-/* retrieve the ROM in 4k blocks */
-static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
-                           int offset, int len)
-{
-       acpi_status status;
-       union acpi_object atrm_arg_elements[2], *obj;
-       struct acpi_object_list atrm_arg;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
-
-       atrm_arg.count = 2;
-       atrm_arg.pointer = &atrm_arg_elements[0];
-
-       atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
-       atrm_arg_elements[0].integer.value = offset;
-
-       atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
-       atrm_arg_elements[1].integer.value = len;
-
-       status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
-       if (ACPI_FAILURE(status)) {
-               printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
-               return -ENODEV;
-       }
-
-       obj = (union acpi_object *)buffer.pointer;
-       memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
-       len = obj->buffer.length;
-       kfree(buffer.pointer);
-       return len;
-}
-
-bool radeon_atrm_supported(struct pci_dev *pdev)
-{
-       /* get the discrete ROM only via ATRM */
-       if (!radeon_atpx_priv.atpx_detected)
-               return false;
-
-       if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev))
-               return false;
-       return true;
-}
-
-
-int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
-{
-       return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len);
-}
-
 static int radeon_atpx_get_version(acpi_handle handle)
 {
        acpi_status status;
@@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
 {
-       acpi_handle dhandle, atpx_handle, atrm_handle;
+       acpi_handle dhandle, atpx_handle;
        acpi_status status;
 
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
@@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
        if (ACPI_FAILURE(status))
                return false;
 
-       status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
-       if (ACPI_FAILURE(status))
-               return false;
-
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx_handle = atpx_handle;
-       radeon_atpx_priv.atrm_handle = atrm_handle;
        return true;
 }
 
index 501f488..d306cc8 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 /*
  * BIOS.
  */
@@ -98,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev)
        return true;
 }
 
+#ifdef CONFIG_ACPI
 /* ATRM is used to get the BIOS on the discrete cards in
  * dual-gpu systems.
  */
+/* retrieve the ROM in 4k blocks */
+#define ATRM_BIOS_PAGE 4096
+/**
+ * radeon_atrm_call - fetch a chunk of the vbios
+ *
+ * @atrm_handle: acpi ATRM handle
+ * @bios: vbios image pointer
+ * @offset: offset of vbios image data to fetch
+ * @len: length of vbios image data to fetch
+ *
+ * Executes ATRM to fetch a chunk of the discrete
+ * vbios image on PX systems (all asics).
+ * Returns the length of the buffer fetched.
+ */
+static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
+                           int offset, int len)
+{
+       acpi_status status;
+       union acpi_object atrm_arg_elements[2], *obj;
+       struct acpi_object_list atrm_arg;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
+
+       atrm_arg.count = 2;
+       atrm_arg.pointer = &atrm_arg_elements[0];
+
+       atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
+       atrm_arg_elements[0].integer.value = offset;
+
+       atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
+       atrm_arg_elements[1].integer.value = len;
+
+       status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
+       if (ACPI_FAILURE(status)) {
+               printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
+               return -ENODEV;
+       }
+
+       obj = (union acpi_object *)buffer.pointer;
+       memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+       len = obj->buffer.length;
+       kfree(buffer.pointer);
+       return len;
+}
+
 static bool radeon_atrm_get_bios(struct radeon_device *rdev)
 {
        int ret;
        int size = 256 * 1024;
        int i;
+       struct pci_dev *pdev = NULL;
+       acpi_handle dhandle, atrm_handle;
+       acpi_status status;
+       bool found = false;
+
+       /* ATRM is for the discrete card only */
+       if (rdev->flags & RADEON_IS_IGP)
+               return false;
+
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+               dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
+               if (!dhandle)
+                       continue;
+
+               status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
+               if (!ACPI_FAILURE(status)) {
+                       found = true;
+                       break;
+               }
+       }
 
-       if (!radeon_atrm_supported(rdev->pdev))
+       if (!found)
                return false;
 
        rdev->bios = kmalloc(size, GFP_KERNEL);
@@ -117,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
        }
 
        for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
-               ret = radeon_atrm_get_bios_chunk(rdev->bios,
-                                                (i * ATRM_BIOS_PAGE),
-                                                ATRM_BIOS_PAGE);
+               ret = radeon_atrm_call(atrm_handle,
+                                      rdev->bios,
+                                      (i * ATRM_BIOS_PAGE),
+                                      ATRM_BIOS_PAGE);
                if (ret < ATRM_BIOS_PAGE)
                        break;
        }
@@ -130,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
        }
        return true;
 }
+#else
+static inline bool radeon_atrm_get_bios(struct radeon_device *rdev)
+{
+       return false;
+}
+#endif
 
 static bool ni_read_disabled_bios(struct radeon_device *rdev)
 {
@@ -476,6 +549,61 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)
                return legacy_read_disabled_bios(rdev);
 }
 
+#ifdef CONFIG_ACPI
+static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+       bool ret = false;
+       struct acpi_table_header *hdr;
+       acpi_size tbl_size;
+       UEFI_ACPI_VFCT *vfct;
+       GOP_VBIOS_CONTENT *vbios;
+       VFCT_IMAGE_HEADER *vhdr;
+
+       if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
+               return false;
+       if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
+               DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
+               goto out_unmap;
+       }
+
+       vfct = (UEFI_ACPI_VFCT *)hdr;
+       if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
+               DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
+               goto out_unmap;
+       }
+
+       vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
+       vhdr = &vbios->VbiosHeader;
+       DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
+                       vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
+                       vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
+
+       if (vhdr->PCIBus != rdev->pdev->bus->number ||
+           vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) ||
+           vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) ||
+           vhdr->VendorID != rdev->pdev->vendor ||
+           vhdr->DeviceID != rdev->pdev->device) {
+               DRM_INFO("ACPI VFCT table is not for this card\n");
+               goto out_unmap;
+       };
+
+       if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
+               DRM_ERROR("ACPI VFCT image truncated\n");
+               goto out_unmap;
+       }
+
+       rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
+       ret = !!rdev->bios;
+
+out_unmap:
+       return ret;
+}
+#else
+static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
+{
+       return false;
+}
+#endif
 
 bool radeon_get_bios(struct radeon_device *rdev)
 {
@@ -483,6 +611,8 @@ bool radeon_get_bios(struct radeon_device *rdev)
        uint16_t tmp;
 
        r = radeon_atrm_get_bios(rdev);
+       if (r == false)
+               r = radeon_acpi_vfct_bios(rdev);
        if (r == false)
                r = igp_read_bios_from_vram(rdev);
        if (r == false)
index d7269f4..27d22d7 100644 (file)
  *   2.18.0 - r600-eg: allow "invalid" DB formats
  *   2.19.0 - r600-eg: MSAA textures
  *   2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
+ *   2.21.0 - r600-r700: FMASK and CMASK
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       20
+#define KMS_DRIVER_MINOR       21
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 1cb014b..9024e72 100644 (file)
@@ -132,6 +132,7 @@ int radeon_bo_create(struct radeon_device *rdev,
        acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
                                       sizeof(struct radeon_bo));
 
+retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
@@ -145,8 +146,6 @@ int radeon_bo_create(struct radeon_device *rdev,
        bo->surface_reg = -1;
        INIT_LIST_HEAD(&bo->list);
        INIT_LIST_HEAD(&bo->va);
-
-retry:
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
        down_read(&rdev->pm.mclk_lock);
index ec79b37..43c431a 100644 (file)
@@ -706,6 +706,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig
        if (radeon_debugfs_ring_init(rdev, ring)) {
                DRM_ERROR("Failed to register debugfs file for rings !\n");
        }
+       radeon_ring_lockup_update(ring);
        return 0;
 }
 
index 5e659b0..f93e45d 100644 (file)
@@ -744,14 +744,6 @@ r600 0x9400
 0x00028C38 CB_CLRCMP_DST
 0x00028C3C CB_CLRCMP_MSK
 0x00028C34 CB_CLRCMP_SRC
-0x00028100 CB_COLOR0_MASK
-0x00028104 CB_COLOR1_MASK
-0x00028108 CB_COLOR2_MASK
-0x0002810C CB_COLOR3_MASK
-0x00028110 CB_COLOR4_MASK
-0x00028114 CB_COLOR5_MASK
-0x00028118 CB_COLOR6_MASK
-0x0002811C CB_COLOR7_MASK
 0x00028808 CB_COLOR_CONTROL
 0x0002842C CB_FOG_BLUE
 0x00028428 CB_FOG_GREEN