Commit 516e7797 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull drm fixes from Dave Airlie:
 "gma500 build fix + some regression fixes for nouveau/radeon"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/radeon: Only warn if the intra-domain offset actually exceeds the limit.
  drm/radeon/kms: add htile support to the cs checker v3
  drm/radeon/kms/atom: force bpc to 8 for now
  drm/nouveau/i2c: fix thinko/regression on really old chipsets
  drm/nouveau: default to 8bpc for non-LVDS panels if EDID isn't useful
  drm/nouveau: fix thinko causing init to fail on cards without accel
  gma500: medfield: fix build without CONFIG_BACKLIGHT_CLASS_DEVICE
parents 735e941c d936622c
...@@ -244,7 +244,6 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, ...@@ -244,7 +244,6 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
uint64_t value) uint64_t value)
{ {
struct drm_encoder *encoder = connector->encoder; struct drm_encoder *encoder = connector->encoder;
struct backlight_device *psb_bd;
if (!strcmp(property->name, "scaling mode") && encoder) { if (!strcmp(property->name, "scaling mode") && encoder) {
struct psb_intel_crtc *psb_crtc = struct psb_intel_crtc *psb_crtc =
...@@ -301,11 +300,15 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, ...@@ -301,11 +300,15 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
value)) value))
goto set_prop_error; goto set_prop_error;
else { else {
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
struct backlight_device *psb_bd;
psb_bd = mdfld_get_backlight_device(); psb_bd = mdfld_get_backlight_device();
if (psb_bd) { if (psb_bd) {
psb_bd->props.brightness = value; psb_bd->props.brightness = value;
mdfld_set_brightness(psb_bd); mdfld_set_brightness(psb_bd);
} }
#endif
} }
} }
set_prop_done: set_prop_done:
......
...@@ -654,10 +654,13 @@ nouveau_connector_detect_depth(struct drm_connector *connector) ...@@ -654,10 +654,13 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
if (nv_connector->edid && connector->display_info.bpc) if (nv_connector->edid && connector->display_info.bpc)
return; return;
/* if not, we're out of options unless we're LVDS, default to 6bpc */ /* if not, we're out of options unless we're LVDS, default to 8bpc */
connector->display_info.bpc = 6; if (nv_encoder->dcb->type != OUTPUT_LVDS) {
if (nv_encoder->dcb->type != OUTPUT_LVDS) connector->display_info.bpc = 8;
return; return;
}
connector->display_info.bpc = 6;
/* LVDS: panel straps */ /* LVDS: panel straps */
if (bios->fp_no_ddc) { if (bios->fp_no_ddc) {
......
...@@ -315,8 +315,8 @@ nouveau_i2c_init(struct drm_device *dev) ...@@ -315,8 +315,8 @@ nouveau_i2c_init(struct drm_device *dev)
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->vbios; struct nvbios *bios = &dev_priv->vbios;
struct nouveau_i2c_chan *port; struct nouveau_i2c_chan *port;
u8 version = 0x00, entries, recordlen;
u8 *i2c, *entry, legacy[2][4] = {}; u8 *i2c, *entry, legacy[2][4] = {};
u8 version, entries, recordlen;
int ret, i; int ret, i;
INIT_LIST_HEAD(&dev_priv->i2c_ports); INIT_LIST_HEAD(&dev_priv->i2c_ports);
...@@ -346,12 +346,12 @@ nouveau_i2c_init(struct drm_device *dev) ...@@ -346,12 +346,12 @@ nouveau_i2c_init(struct drm_device *dev)
if (i2c[7]) legacy[1][1] = i2c[7]; if (i2c[7]) legacy[1][1] = i2c[7];
} }
if (i2c && version >= 0x30) { if (version >= 0x30) {
entry = i2c[1] + i2c; entry = i2c[1] + i2c;
entries = i2c[2]; entries = i2c[2];
recordlen = i2c[3]; recordlen = i2c[3];
} else } else
if (i2c) { if (version) {
entry = i2c; entry = i2c;
entries = 16; entries = 16;
recordlen = 4; recordlen = 4;
......
...@@ -852,7 +852,7 @@ nouveau_card_init(struct drm_device *dev) ...@@ -852,7 +852,7 @@ nouveau_card_init(struct drm_device *dev)
if (ret) if (ret)
goto out_pm; goto out_pm;
if (!dev_priv->noaccel) { if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
ret = nouveau_card_channel_init(dev); ret = nouveau_card_channel_init(dev);
if (ret) if (ret)
goto out_fence; goto out_fence;
......
...@@ -588,8 +588,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -588,8 +588,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (encoder->crtc == crtc) { if (encoder->crtc == crtc) {
radeon_encoder = to_radeon_encoder(encoder); radeon_encoder = to_radeon_encoder(encoder);
connector = radeon_get_connector_for_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder);
if (connector && connector->display_info.bpc) /* if (connector && connector->display_info.bpc)
bpc = connector->display_info.bpc; bpc = connector->display_info.bpc; */
encoder_mode = atombios_get_encoder_mode(encoder); encoder_mode = atombios_get_encoder_mode(encoder);
is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
...@@ -965,7 +965,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -965,7 +965,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
struct radeon_connector_atom_dig *dig_connector = struct radeon_connector_atom_dig *dig_connector =
radeon_connector->con_priv; radeon_connector->con_priv;
int dp_clock; int dp_clock;
bpc = connector->display_info.bpc;
/* if (connector->display_info.bpc)
bpc = connector->display_info.bpc; */
switch (encoder_mode) { switch (encoder_mode) {
case ATOM_ENCODER_MODE_DP_MST: case ATOM_ENCODER_MODE_DP_MST:
......
...@@ -405,10 +405,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], ...@@ -405,10 +405,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE],
/* get bpc from the EDID */ /* get bpc from the EDID */
static int convert_bpc_to_bpp(int bpc) static int convert_bpc_to_bpp(int bpc)
{ {
#if 0
if (bpc == 0) if (bpc == 0)
return 24; return 24;
else else
return bpc * 3; return bpc * 3;
#endif
return 24;
} }
/* get the max pix clock supported by the link rate and lane num */ /* get the max pix clock supported by the link rate and lane num */
......
...@@ -541,7 +541,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo ...@@ -541,7 +541,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo
dp_clock = dig_connector->dp_clock; dp_clock = dig_connector->dp_clock;
dp_lane_count = dig_connector->dp_lane_count; dp_lane_count = dig_connector->dp_lane_count;
hpd_id = radeon_connector->hpd.hpd; hpd_id = radeon_connector->hpd.hpd;
bpc = connector->display_info.bpc; /* bpc = connector->display_info.bpc; */
} }
/* no dig encoder assigned */ /* no dig encoder assigned */
...@@ -1159,7 +1159,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, ...@@ -1159,7 +1159,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder,
dp_lane_count = dig_connector->dp_lane_count; dp_lane_count = dig_connector->dp_lane_count;
connector_object_id = connector_object_id =
(radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
bpc = connector->display_info.bpc; /* bpc = connector->display_info.bpc; */
} }
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
......
...@@ -80,6 +80,9 @@ struct evergreen_cs_track { ...@@ -80,6 +80,9 @@ struct evergreen_cs_track {
bool cb_dirty; bool cb_dirty;
bool db_dirty; bool db_dirty;
bool streamout_dirty; bool streamout_dirty;
u32 htile_offset;
u32 htile_surface;
struct radeon_bo *htile_bo;
}; };
static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) static u32 evergreen_cs_get_aray_mode(u32 tiling_flags)
...@@ -144,6 +147,9 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) ...@@ -144,6 +147,9 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track)
track->db_s_read_bo = NULL; track->db_s_read_bo = NULL;
track->db_s_write_bo = NULL; track->db_s_write_bo = NULL;
track->db_dirty = true; track->db_dirty = true;
track->htile_bo = NULL;
track->htile_offset = 0xFFFFFFFF;
track->htile_surface = 0;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
track->vgt_strmout_size[i] = 0; track->vgt_strmout_size[i] = 0;
...@@ -444,6 +450,62 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i ...@@ -444,6 +450,62 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i
return 0; return 0;
} }
static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
unsigned nbx, unsigned nby)
{
struct evergreen_cs_track *track = p->track;
unsigned long size;
if (track->htile_bo == NULL) {
dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
__func__, __LINE__, track->db_z_info);
return -EINVAL;
}
if (G_028ABC_LINEAR(track->htile_surface)) {
/* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */
nbx = round_up(nbx, 16 * 8);
/* height is npipes htiles aligned == npipes * 8 pixel aligned */
nby = round_up(nby, track->npipes * 8);
} else {
switch (track->npipes) {
case 8:
nbx = round_up(nbx, 64 * 8);
nby = round_up(nby, 64 * 8);
break;
case 4:
nbx = round_up(nbx, 64 * 8);
nby = round_up(nby, 32 * 8);
break;
case 2:
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 32 * 8);
break;
case 1:
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 16 * 8);
break;
default:
dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
__func__, __LINE__, track->npipes);
return -EINVAL;
}
}
/* compute number of htile */
nbx = nbx / 8;
nby = nby / 8;
size = nbx * nby * 4;
size += track->htile_offset;
if (size > radeon_bo_size(track->htile_bo)) {
dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
__func__, __LINE__, radeon_bo_size(track->htile_bo),
size, nbx, nby);
return -EINVAL;
}
return 0;
}
static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
{ {
struct evergreen_cs_track *track = p->track; struct evergreen_cs_track *track = p->track;
...@@ -530,6 +592,14 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) ...@@ -530,6 +592,14 @@ static int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p)
return -EINVAL; return -EINVAL;
} }
/* hyperz */
if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
if (r) {
return r;
}
}
return 0; return 0;
} }
...@@ -617,6 +687,14 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) ...@@ -617,6 +687,14 @@ static int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p)
return -EINVAL; return -EINVAL;
} }
/* hyperz */
if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) {
r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby);
if (r) {
return r;
}
}
return 0; return 0;
} }
...@@ -850,7 +928,7 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p) ...@@ -850,7 +928,7 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)
return r; return r;
} }
/* Check depth buffer */ /* Check depth buffer */
if (G_028800_Z_WRITE_ENABLE(track->db_depth_control)) { if (G_028800_Z_ENABLE(track->db_depth_control)) {
r = evergreen_cs_track_validate_depth(p); r = evergreen_cs_track_validate_depth(p);
if (r) if (r)
return r; return r;
...@@ -1616,6 +1694,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) ...@@ -1616,6 +1694,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
track->cb_color_bo[tmp] = reloc->robj; track->cb_color_bo[tmp] = reloc->robj;
track->cb_dirty = true; track->cb_dirty = true;
break; break;
case DB_HTILE_DATA_BASE:
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG "
"0x%04X\n", reg);
return -EINVAL;
}
track->htile_offset = radeon_get_ib_value(p, idx);
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->htile_bo = reloc->robj;
track->db_dirty = true;
break;
case DB_HTILE_SURFACE:
/* 8x8 only */
track->htile_surface = radeon_get_ib_value(p, idx);
track->db_dirty = true;
break;
case CB_IMMED0_BASE: case CB_IMMED0_BASE:
case CB_IMMED1_BASE: case CB_IMMED1_BASE:
case CB_IMMED2_BASE: case CB_IMMED2_BASE:
...@@ -1628,7 +1723,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) ...@@ -1628,7 +1723,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
case CB_IMMED9_BASE: case CB_IMMED9_BASE:
case CB_IMMED10_BASE: case CB_IMMED10_BASE:
case CB_IMMED11_BASE: case CB_IMMED11_BASE:
case DB_HTILE_DATA_BASE:
case SQ_PGM_START_FS: case SQ_PGM_START_FS:
case SQ_PGM_START_ES: case SQ_PGM_START_ES:
case SQ_PGM_START_VS: case SQ_PGM_START_VS:
......
...@@ -991,6 +991,14 @@ ...@@ -991,6 +991,14 @@
#define G_028008_SLICE_MAX(x) (((x) >> 13) & 0x7FF) #define G_028008_SLICE_MAX(x) (((x) >> 13) & 0x7FF)
#define C_028008_SLICE_MAX 0xFF001FFF #define C_028008_SLICE_MAX 0xFF001FFF
#define DB_HTILE_DATA_BASE 0x28014 #define DB_HTILE_DATA_BASE 0x28014
#define DB_HTILE_SURFACE 0x28abc
#define S_028ABC_HTILE_WIDTH(x) (((x) & 0x1) << 0)
#define G_028ABC_HTILE_WIDTH(x) (((x) >> 0) & 0x1)
#define C_028ABC_HTILE_WIDTH 0xFFFFFFFE
#define S_028ABC_HTILE_HEIGHT(x) (((x) & 0x1) << 1)
#define G_028ABC_HTILE_HEIGHT(x) (((x) >> 1) & 0x1)
#define C_028ABC_HTILE_HEIGHT 0xFFFFFFFD
#define G_028ABC_LINEAR(x) (((x) >> 2) & 0x1)
#define DB_Z_INFO 0x28040 #define DB_Z_INFO 0x28040
# define Z_ARRAY_MODE(x) ((x) << 4) # define Z_ARRAY_MODE(x) ((x) << 4)
# define DB_TILE_SPLIT(x) (((x) & 0x7) << 8) # define DB_TILE_SPLIT(x) (((x) & 0x7) << 8)
......
...@@ -78,6 +78,9 @@ struct r600_cs_track { ...@@ -78,6 +78,9 @@ struct r600_cs_track {
bool cb_dirty; bool cb_dirty;
bool db_dirty; bool db_dirty;
bool streamout_dirty; bool streamout_dirty;
struct radeon_bo *htile_bo;
u64 htile_offset;
u32 htile_surface;
}; };
#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 } #define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc, CHIP_R600 }
...@@ -321,6 +324,9 @@ static void r600_cs_track_init(struct r600_cs_track *track) ...@@ -321,6 +324,9 @@ static void r600_cs_track_init(struct r600_cs_track *track)
track->db_depth_size_idx = 0; track->db_depth_size_idx = 0;
track->db_depth_control = 0xFFFFFFFF; track->db_depth_control = 0xFFFFFFFF;
track->db_dirty = true; track->db_dirty = true;
track->htile_bo = NULL;
track->htile_offset = 0xFFFFFFFF;
track->htile_surface = 0;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
track->vgt_strmout_size[i] = 0; track->vgt_strmout_size[i] = 0;
...@@ -455,12 +461,256 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) ...@@ -455,12 +461,256 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
return 0; return 0;
} }
static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
{
struct r600_cs_track *track = p->track;
u32 nviews, bpe, ntiles, size, slice_tile_max, tmp;
u32 height_align, pitch_align, depth_align;
u32 pitch = 8192;
u32 height = 8192;
u64 base_offset, base_align;
struct array_mode_checker array_check;
int array_mode;
volatile u32 *ib = p->ib->ptr;
if (track->db_bo == NULL) {
dev_warn(p->dev, "z/stencil with no depth buffer\n");
return -EINVAL;
}
switch (G_028010_FORMAT(track->db_depth_info)) {
case V_028010_DEPTH_16:
bpe = 2;
break;
case V_028010_DEPTH_X8_24:
case V_028010_DEPTH_8_24:
case V_028010_DEPTH_X8_24_FLOAT:
case V_028010_DEPTH_8_24_FLOAT:
case V_028010_DEPTH_32_FLOAT:
bpe = 4;
break;
case V_028010_DEPTH_X24_8_32_FLOAT:
bpe = 8;
break;
default:
dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
return -EINVAL;
}
if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
if (!track->db_depth_size_idx) {
dev_warn(p->dev, "z/stencil buffer size not set\n");
return -EINVAL;
}
tmp = radeon_bo_size(track->db_bo) - track->db_offset;
tmp = (tmp / bpe) >> 6;
if (!tmp) {
dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
track->db_depth_size, bpe, track->db_offset,
radeon_bo_size(track->db_bo));
return -EINVAL;
}
ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
} else {
size = radeon_bo_size(track->db_bo);
/* pitch in pixels */
pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
slice_tile_max *= 64;
height = slice_tile_max / pitch;
if (height > 8192)
height = 8192;
base_offset = track->db_bo_mc + track->db_offset;
array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
array_check.array_mode = array_mode;
array_check.group_size = track->group_size;
array_check.nbanks = track->nbanks;
array_check.npipes = track->npipes;
array_check.nsamples = track->nsamples;
array_check.blocksize = bpe;
if (r600_get_array_mode_alignment(&array_check,
&pitch_align, &height_align, &depth_align, &base_align)) {
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_028010_ARRAY_MODE(track->db_depth_info),
track->db_depth_info);
return -EINVAL;
}
switch (array_mode) {
case V_028010_ARRAY_1D_TILED_THIN1:
/* don't break userspace */
height &= ~0x7;
break;
case V_028010_ARRAY_2D_TILED_THIN1:
break;
default:
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_028010_ARRAY_MODE(track->db_depth_info),
track->db_depth_info);
return -EINVAL;
}
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
__func__, __LINE__, pitch, pitch_align, array_mode);
return -EINVAL;
}
if (!IS_ALIGNED(height, height_align)) {
dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
__func__, __LINE__, height, height_align, array_mode);
return -EINVAL;
}
if (!IS_ALIGNED(base_offset, base_align)) {
dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__,
base_offset, base_align, array_mode);
return -EINVAL;
}
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;
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,
track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
radeon_bo_size(track->db_bo));
return -EINVAL;
}
}
/* hyperz */
if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
unsigned long size;
unsigned nbx, nby;
if (track->htile_bo == NULL) {
dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
__func__, __LINE__, track->db_depth_info);
return -EINVAL;
}
if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n",
__func__, __LINE__, track->db_depth_size);
return -EINVAL;
}
nbx = pitch;
nby = height;
if (G_028D24_LINEAR(track->htile_surface)) {
/* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */
nbx = round_up(nbx, 16 * 8);
/* nby is npipes htiles aligned == npipes * 8 pixel aligned */
nby = round_up(nby, track->npipes * 8);
} else {
/* htile widht & nby (8 or 4) make 2 bits number */
tmp = track->htile_surface & 3;
/* align is htile align * 8, htile align vary according to
* number of pipe and tile width and nby
*/
switch (track->npipes) {
case 8:
switch (tmp) {
case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
nbx = round_up(nbx, 64 * 8);
nby = round_up(nby, 64 * 8);
break;
case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 64 * 8);
nby = round_up(nby, 32 * 8);
break;
case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 32 * 8);
break;
default:
return -EINVAL;
}
break;
case 4:
switch (tmp) {
case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
nbx = round_up(nbx, 64 * 8);
nby = round_up(nby, 32 * 8);
break;
case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 32 * 8);
break;
case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 16 * 8);
break;
default:
return -EINVAL;
}
break;
case 2:
switch (tmp) {
case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 32 * 8);
break;
case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 16 * 8);
break;
case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 16 * 8);
nby = round_up(nby, 16 * 8);
break;
default:
return -EINVAL;
}
break;
case 1:
switch (tmp) {
case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
nbx = round_up(nbx, 32 * 8);
nby = round_up(nby, 16 * 8);
break;
case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 16 * 8);
nby = round_up(nby, 16 * 8);
break;
case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
nbx = round_up(nbx, 16 * 8);
nby = round_up(nby, 8 * 8);
break;
default:
return -EINVAL;
}
break;
default:
dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
__func__, __LINE__, track->npipes);
return -EINVAL;
}
}
/* compute number of htile */
nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4;
nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4;
size = nbx * nby * 4;
size += track->htile_offset;
if (size > radeon_bo_size(track->htile_bo)) {
dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
__func__, __LINE__, radeon_bo_size(track->htile_bo),
size, nbx, nby);
return -EINVAL;
}
}
track->db_dirty = false;
return 0;
}
static int r600_cs_track_check(struct radeon_cs_parser *p) static int r600_cs_track_check(struct radeon_cs_parser *p)
{ {
struct r600_cs_track *track = p->track; struct r600_cs_track *track = p->track;
u32 tmp; u32 tmp;
int r, i; int r, i;
volatile u32 *ib = p->ib->ptr;
/* on legacy kernel we don't perform advanced check */ /* on legacy kernel we don't perform advanced check */
if (p->rdev == NULL) if (p->rdev == NULL)
...@@ -513,124 +763,14 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) ...@@ -513,124 +763,14 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
track->cb_dirty = false; track->cb_dirty = false;
} }
if (track->db_dirty) { /* Check depth buffer */
/* Check depth buffer */ if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
if (G_028800_STENCIL_ENABLE(track->db_depth_control) || G_028800_Z_ENABLE(track->db_depth_control))) {
G_028800_Z_ENABLE(track->db_depth_control)) { r = r600_cs_track_validate_db(p);
u32 nviews, bpe, ntiles, size, slice_tile_max; if (r)
u32 height, height_align, pitch, pitch_align, depth_align; return r;
u64 base_offset, base_align;
struct array_mode_checker array_check;
int array_mode;
if (track->db_bo == NULL) {
dev_warn(p->dev, "z/stencil with no depth buffer\n");
return -EINVAL;
}
if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
dev_warn(p->dev, "this kernel doesn't support z/stencil htile\n");
return -EINVAL;
}
switch (G_028010_FORMAT(track->db_depth_info)) {
case V_028010_DEPTH_16:
bpe = 2;
break;
case V_028010_DEPTH_X8_24:
case V_028010_DEPTH_8_24:
case V_028010_DEPTH_X8_24_FLOAT:
case V_028010_DEPTH_8_24_FLOAT:
case V_028010_DEPTH_32_FLOAT:
bpe = 4;
break;
case V_028010_DEPTH_X24_8_32_FLOAT:
bpe = 8;
break;
default:
dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
return -EINVAL;
}
if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
if (!track->db_depth_size_idx) {
dev_warn(p->dev, "z/stencil buffer size not set\n");
return -EINVAL;
}
tmp = radeon_bo_size(track->db_bo) - track->db_offset;
tmp = (tmp / bpe) >> 6;
if (!tmp) {
dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
track->db_depth_size, bpe, track->db_offset,
radeon_bo_size(track->db_bo));
return -EINVAL;
}
ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
} else {
size = radeon_bo_size(track->db_bo);
/* pitch in pixels */
pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
slice_tile_max *= 64;
height = slice_tile_max / pitch;
if (height > 8192)
height = 8192;
base_offset = track->db_bo_mc + track->db_offset;
array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
array_check.array_mode = array_mode;
array_check.group_size = track->group_size;
array_check.nbanks = track->nbanks;
array_check.npipes = track->npipes;
array_check.nsamples = track->nsamples;
array_check.blocksize = bpe;
if (r600_get_array_mode_alignment(&array_check,
&pitch_align, &height_align, &depth_align, &base_align)) {
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_028010_ARRAY_MODE(track->db_depth_info),
track->db_depth_info);
return -EINVAL;
}
switch (array_mode) {
case V_028010_ARRAY_1D_TILED_THIN1:
/* don't break userspace */
height &= ~0x7;
break;
case V_028010_ARRAY_2D_TILED_THIN1:
break;
default:
dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
G_028010_ARRAY_MODE(track->db_depth_info),
track->db_depth_info);
return -EINVAL;
}
if (!IS_ALIGNED(pitch, pitch_align)) {
dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
__func__, __LINE__, pitch, pitch_align, array_mode);
return -EINVAL;
}
if (!IS_ALIGNED(height, height_align)) {
dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
__func__, __LINE__, height, height_align, array_mode);
return -EINVAL;
}
if (!IS_ALIGNED(base_offset, base_align)) {
dev_warn(p->dev, "%s offset[%d] 0x%llx, 0x%llx, %d not aligned\n", __func__, i,
base_offset, base_align, array_mode);
return -EINVAL;
}
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;
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,
track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
radeon_bo_size(track->db_bo));
return -EINVAL;
}
}
}
track->db_dirty = false;
} }
return 0; return 0;
} }
...@@ -1244,6 +1384,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) ...@@ -1244,6 +1384,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
track->db_dirty = true; track->db_dirty = true;
break; break;
case DB_HTILE_DATA_BASE: case DB_HTILE_DATA_BASE:
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG "
"0x%04X\n", reg);
return -EINVAL;
}
track->htile_offset = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->htile_bo = reloc->robj;
track->db_dirty = true;
break;
case DB_HTILE_SURFACE:
track->htile_surface = radeon_get_ib_value(p, idx);
track->db_dirty = true;
break;
case SQ_PGM_START_FS: case SQ_PGM_START_FS:
case SQ_PGM_START_ES: case SQ_PGM_START_ES:
case SQ_PGM_START_VS: case SQ_PGM_START_VS:
......
...@@ -195,6 +195,14 @@ ...@@ -195,6 +195,14 @@
#define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) #define PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31)
#define DB_DEPTH_BASE 0x2800C #define DB_DEPTH_BASE 0x2800C
#define DB_HTILE_DATA_BASE 0x28014 #define DB_HTILE_DATA_BASE 0x28014
#define DB_HTILE_SURFACE 0x28D24
#define S_028D24_HTILE_WIDTH(x) (((x) & 0x1) << 0)
#define G_028D24_HTILE_WIDTH(x) (((x) >> 0) & 0x1)
#define C_028D24_HTILE_WIDTH 0xFFFFFFFE
#define S_028D24_HTILE_HEIGHT(x) (((x) & 0x1) << 1)
#define G_028D24_HTILE_HEIGHT(x) (((x) >> 1) & 0x1)
#define C_028D24_HTILE_HEIGHT 0xFFFFFFFD
#define G_028D24_LINEAR(x) (((x) >> 2) & 0x1)
#define DB_WATERMARKS 0x9838 #define DB_WATERMARKS 0x9838
#define DEPTH_FREE(x) ((x) << 0) #define DEPTH_FREE(x) ((x) << 0)
#define DEPTH_FLUSH(x) ((x) << 5) #define DEPTH_FLUSH(x) ((x) << 5)
......
...@@ -233,7 +233,17 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, ...@@ -233,7 +233,17 @@ int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
bo->pin_count++; bo->pin_count++;
if (gpu_addr) if (gpu_addr)
*gpu_addr = radeon_bo_gpu_offset(bo); *gpu_addr = radeon_bo_gpu_offset(bo);
WARN_ON_ONCE(max_offset != 0);
if (max_offset != 0) {
u64 domain_start;
if (domain == RADEON_GEM_DOMAIN_VRAM)
domain_start = bo->rdev->mc.vram_start;
else
domain_start = bo->rdev->mc.gtt_start;
WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset);
}
return 0; return 0;
} }
radeon_ttm_placement_from_domain(bo, domain); radeon_ttm_placement_from_domain(bo, domain);
......
...@@ -509,7 +509,6 @@ cayman 0x9400 ...@@ -509,7 +509,6 @@ cayman 0x9400
0x00028AA8 IA_MULTI_VGT_PARAM 0x00028AA8 IA_MULTI_VGT_PARAM
0x00028AB4 VGT_REUSE_OFF 0x00028AB4 VGT_REUSE_OFF
0x00028AB8 VGT_VTX_CNT_EN 0x00028AB8 VGT_VTX_CNT_EN
0x00028ABC DB_HTILE_SURFACE
0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
0x00028AC8 DB_PRELOAD_CONTROL 0x00028AC8 DB_PRELOAD_CONTROL
......
...@@ -519,7 +519,6 @@ evergreen 0x9400 ...@@ -519,7 +519,6 @@ evergreen 0x9400
0x00028AA4 VGT_INSTANCE_STEP_RATE_1 0x00028AA4 VGT_INSTANCE_STEP_RATE_1
0x00028AB4 VGT_REUSE_OFF 0x00028AB4 VGT_REUSE_OFF
0x00028AB8 VGT_VTX_CNT_EN 0x00028AB8 VGT_VTX_CNT_EN
0x00028ABC DB_HTILE_SURFACE
0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC0 DB_SRESULTS_COMPARE_STATE0
0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC4 DB_SRESULTS_COMPARE_STATE1
0x00028AC8 DB_PRELOAD_CONTROL 0x00028AC8 DB_PRELOAD_CONTROL
......
...@@ -713,7 +713,6 @@ r600 0x9400 ...@@ -713,7 +713,6 @@ r600 0x9400
0x0000A710 TD_VS_SAMPLER17_BORDER_RED 0x0000A710 TD_VS_SAMPLER17_BORDER_RED
0x00009508 TA_CNTL_AUX 0x00009508 TA_CNTL_AUX
0x0002802C DB_DEPTH_CLEAR 0x0002802C DB_DEPTH_CLEAR
0x00028D24 DB_HTILE_SURFACE
0x00028D34 DB_PREFETCH_LIMIT 0x00028D34 DB_PREFETCH_LIMIT
0x00028D30 DB_PRELOAD_CONTROL 0x00028D30 DB_PRELOAD_CONTROL
0x00028D0C DB_RENDER_CONTROL 0x00028D0C DB_RENDER_CONTROL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment