Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm/radeon/kms/blit: fix blit copy for very large buffers drm/radeon/kms: fix TRAVIS panel setup drm/radeon: fix use after free in ATRM bios reading code. drm/radeon/kms: Fix device tree linkage of DP i2c buses too drm/radeon: Set DESKTOP_HEIGHT register to the framebuffer (not mode) height. drm/radeon/kms: disable output polling when suspended drm/nv50/pm: signedness bug in nv50_pm_clocks_pre() drm/nouveau/gem: fix fence_sync race / oops drm/nouveau: fix typo on mxmdcb option drm/nouveau/mxm: pretend to succeed, even if we can't shadow the MXM-SIS drm/nouveau/disp: check that panel power gpio is enabled at init time
This commit is contained in:
commit
24b36da33c
|
@ -54,9 +54,10 @@ struct bit_entry {
|
|||
int bit_table(struct drm_device *, u8 id, struct bit_entry *);
|
||||
|
||||
enum dcb_gpio_tag {
|
||||
DCB_GPIO_TVDAC0 = 0xc,
|
||||
DCB_GPIO_PANEL_POWER = 0x01,
|
||||
DCB_GPIO_TVDAC0 = 0x0c,
|
||||
DCB_GPIO_TVDAC1 = 0x2d,
|
||||
DCB_GPIO_PWM_FAN = 0x9,
|
||||
DCB_GPIO_PWM_FAN = 0x09,
|
||||
DCB_GPIO_FAN_SENSE = 0x3d,
|
||||
DCB_GPIO_UNUSED = 0xff
|
||||
};
|
||||
|
|
|
@ -219,6 +219,16 @@ nouveau_display_init(struct drm_device *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* power on internal panel if it's not already. the init tables of
|
||||
* some vbios default this to off for some reason, causing the
|
||||
* panel to not work after resume
|
||||
*/
|
||||
if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
|
||||
nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
/* enable polling for external displays */
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
/* enable hotplug interrupts */
|
||||
|
|
|
@ -124,7 +124,7 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n");
|
|||
int nouveau_ctxfw;
|
||||
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
|
||||
MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");
|
||||
int nouveau_mxmdcb = 1;
|
||||
module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
|
||||
|
||||
|
|
|
@ -379,6 +379,25 @@ retry:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
|
||||
{
|
||||
struct nouveau_fence *fence = NULL;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock(&nvbo->bo.bdev->fence_lock);
|
||||
if (nvbo->bo.sync_obj)
|
||||
fence = nouveau_fence_ref(nvbo->bo.sync_obj);
|
||||
spin_unlock(&nvbo->bo.bdev->fence_lock);
|
||||
|
||||
if (fence) {
|
||||
ret = nouveau_fence_sync(fence, chan);
|
||||
nouveau_fence_unref(&fence);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
validate_list(struct nouveau_channel *chan, struct list_head *list,
|
||||
struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
|
||||
|
@ -393,7 +412,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
list_for_each_entry(nvbo, list, entry) {
|
||||
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
|
||||
|
||||
ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
|
||||
ret = validate_sync(chan, nvbo);
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail pre-validate sync\n");
|
||||
return ret;
|
||||
|
@ -416,7 +435,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
|
||||
ret = validate_sync(chan, nvbo);
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail post-validate sync\n");
|
||||
return ret;
|
||||
|
|
|
@ -656,7 +656,16 @@ nouveau_mxm_init(struct drm_device *dev)
|
|||
|
||||
if (mxm_shadow(dev, mxm[0])) {
|
||||
MXM_MSG(dev, "failed to locate valid SIS\n");
|
||||
#if 0
|
||||
/* we should, perhaps, fall back to some kind of limited
|
||||
* mode here if the x86 vbios hasn't already done the
|
||||
* work for us (so we prevent loading with completely
|
||||
* whacked vbios tables).
|
||||
*/
|
||||
return -EINVAL;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
MXM_MSG(dev, "MXMS Version %d.%d\n",
|
||||
|
|
|
@ -495,9 +495,9 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nv50_pm_state *info;
|
||||
struct pll_lims pll;
|
||||
int ret = -EINVAL;
|
||||
int clk, ret = -EINVAL;
|
||||
int N, M, P1, P2;
|
||||
u32 clk, out;
|
||||
u32 out;
|
||||
|
||||
if (dev_priv->chipset == 0xaa ||
|
||||
dev_priv->chipset == 0xac)
|
||||
|
|
|
@ -1184,7 +1184,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
|
||||
|
||||
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
|
||||
crtc->mode.vdisplay);
|
||||
target_fb->height);
|
||||
x &= ~3;
|
||||
y &= ~1;
|
||||
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
|
||||
|
@ -1353,7 +1353,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
|
||||
|
||||
WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
|
||||
crtc->mode.vdisplay);
|
||||
target_fb->height);
|
||||
x &= ~3;
|
||||
y &= ~1;
|
||||
WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
|
||||
|
|
|
@ -564,9 +564,21 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
|
|||
ENCODER_OBJECT_ID_NUTMEG)
|
||||
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
|
||||
else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
|
||||
ENCODER_OBJECT_ID_TRAVIS)
|
||||
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
|
||||
else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
ENCODER_OBJECT_ID_TRAVIS) {
|
||||
u8 id[6];
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
|
||||
if (id[0] == 0x73 &&
|
||||
id[1] == 0x69 &&
|
||||
id[2] == 0x76 &&
|
||||
id[3] == 0x61 &&
|
||||
id[4] == 0x72 &&
|
||||
id[5] == 0x54)
|
||||
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
|
||||
else
|
||||
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
|
||||
} else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
|
||||
if (tmp & 1)
|
||||
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
|
||||
|
|
|
@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)
|
|||
radeon_ring_write(ring, sq_stack_resource_mgmt_2);
|
||||
}
|
||||
|
||||
#define I2F_MAX_BITS 15
|
||||
#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1)
|
||||
#define I2F_SHIFT (24 - I2F_MAX_BITS)
|
||||
|
||||
/*
|
||||
* Converts unsigned integer into 32-bit IEEE floating point representation.
|
||||
* Conversion is not universal and only works for the range from 0
|
||||
* to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
|
||||
* 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
|
||||
* I2F_MAX_BITS can be increased, but that will add to the loop iterations
|
||||
* and slow us down. Conversion is done by shifting the input and counting
|
||||
* down until the first 1 reaches bit position 23. The resulting counter
|
||||
* and the shifted input are, respectively, the exponent and the fraction.
|
||||
* The sign is always zero.
|
||||
*/
|
||||
static uint32_t i2f(uint32_t input)
|
||||
{
|
||||
u32 result, i, exponent, fraction;
|
||||
|
||||
if ((input & 0x3fff) == 0)
|
||||
result = 0; /* 0 is a special case */
|
||||
WARN_ON_ONCE(input > I2F_MAX_INPUT);
|
||||
|
||||
if ((input & I2F_MAX_INPUT) == 0)
|
||||
result = 0;
|
||||
else {
|
||||
exponent = 140; /* exponent biased by 127; */
|
||||
fraction = (input & 0x3fff) << 10; /* cheat and only
|
||||
handle numbers below 2^^15 */
|
||||
for (i = 0; i < 14; i++) {
|
||||
exponent = 126 + I2F_MAX_BITS;
|
||||
fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
|
||||
|
||||
for (i = 0; i < I2F_MAX_BITS; i++) {
|
||||
if (fraction & 0x800000)
|
||||
break;
|
||||
else {
|
||||
fraction = fraction << 1; /* keep
|
||||
shifting left until top bit = 1 */
|
||||
fraction = fraction << 1;
|
||||
exponent = exponent - 1;
|
||||
}
|
||||
}
|
||||
result = exponent << 23 | (fraction & 0x7fffff); /* mask
|
||||
off top bit; assumed 1 */
|
||||
result = exponent << 23 | (fraction & 0x7fffff);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -59,8 +59,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
|
|||
|
||||
obj = (union acpi_object *)buffer.pointer;
|
||||
memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
|
||||
len = obj->buffer.length;
|
||||
kfree(buffer.pointer);
|
||||
return obj->buffer.length;
|
||||
return len;
|
||||
}
|
||||
|
||||
bool radeon_atrm_supported(struct pci_dev *pdev)
|
||||
|
|
|
@ -883,6 +883,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
|
|||
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
|
||||
return 0;
|
||||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
/* turn off display hw */
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
|
||||
|
@ -972,6 +974,8 @@ int radeon_resume_kms(struct drm_device *dev)
|
|||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -958,6 +958,7 @@ struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
|
|||
i2c->rec = *rec;
|
||||
i2c->adapter.owner = THIS_MODULE;
|
||||
i2c->adapter.class = I2C_CLASS_DDC;
|
||||
i2c->adapter.dev.parent = &dev->pdev->dev;
|
||||
i2c->dev = dev;
|
||||
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
|
||||
"Radeon aux bus %s", name);
|
||||
|
|
Loading…
Reference in a new issue