Commit 74a7f6a0 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
  drm/ttm: fix two regressions since move_notify changes
  drm/radeon: avoid deadlock if GPU lockup is detected in ib_pool_get
  drm/radeon: silence out possible lock dependency warning
  drm: Fix authentication kernel crash
  gma500: Fix shmem mapping
  drm/radeon/kms: refine TMDS dual link checks
  drm/radeon/kms: use drm_detect_hdmi_monitor for picking encoder mode
  drm/radeon/kms: rework modeset sequence for DCE41 and DCE5
  drm/radeon/kms: move panel mode setup into encoder mode set
  drm/radeon/kms: move disp eng pll setup to init path
  drm/radeon: finish getting bios earlier
  drm/radeon: fix invalid memory access in radeon_atrm_get_bios()
  drm/radeon/kms: add some missing semaphore init
  drm/radeon/kms: Add an MSI quirk for Dell RS690
  gpu, drm, sis: Don't return uninitialized variable from sis_driver_load()
parents 486bc794 9f1feed2
...@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv, ...@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
* Searches and unlinks the entry in drm_device::magiclist with the magic * Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock. * number hash key, while holding the drm_device::struct_mutex lock.
*/ */
static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{ {
struct drm_magic_entry *pt; struct drm_magic_entry *pt;
struct drm_hash_item *hash; struct drm_hash_item *hash;
...@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic) ...@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
* If there is a magic number in drm_file::magic then use it, otherwise * If there is a magic number in drm_file::magic then use it, otherwise
* searches an unique non-zero magic number and add it associating it with \p * searches an unique non-zero magic number and add it associating it with \p
* file_priv. * file_priv.
* This ioctl needs protection by the drm_global_mutex, which protects
* struct drm_file::magic and struct drm_magic_entry::priv.
*/ */
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{ {
...@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) ...@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
* \return zero if authentication successed, or a negative number otherwise. * \return zero if authentication successed, or a negative number otherwise.
* *
* Checks if \p file_priv is associated with the magic number passed in \arg. * Checks if \p file_priv is associated with the magic number passed in \arg.
* This ioctl needs protection by the drm_global_mutex, which protects
* struct drm_file::magic and struct drm_magic_entry::priv.
*/ */
int drm_authmagic(struct drm_device *dev, void *data, int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
......
...@@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp) ...@@ -487,6 +487,11 @@ int drm_release(struct inode *inode, struct file *filp)
(long)old_encode_dev(file_priv->minor->device), (long)old_encode_dev(file_priv->minor->device),
dev->open_count); dev->open_count);
/* Release any auth tokens that might point to this file_priv,
(do that under the drm_global_mutex) */
if (file_priv->magic)
(void) drm_remove_magic(file_priv->master, file_priv->magic);
/* if the master has gone away we can't do anything with the lock */ /* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master) if (file_priv->minor->master)
drm_master_release(dev, filp); drm_master_release(dev, filp);
......
...@@ -812,6 +812,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) ...@@ -812,6 +812,10 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vma *vma; struct nouveau_vma *vma;
/* ttm can now (stupidly) pass the driver bos it didn't create... */
if (bo->destroy != nouveau_bo_del_ttm)
return;
list_for_each_entry(vma, &nvbo->vma_list, head) { list_for_each_entry(vma, &nvbo->vma_list, head) {
if (new_mem && new_mem->mem_type == TTM_PL_VRAM) { if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
nouveau_vm_map(vma, new_mem->mm_node); nouveau_vm_map(vma, new_mem->mm_node);
......
...@@ -355,15 +355,12 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, ...@@ -355,15 +355,12 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc,
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
} }
static void atombios_disable_ss(struct drm_crtc *crtc) static void atombios_disable_ss(struct radeon_device *rdev, int pll_id)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
u32 ss_cntl; u32 ss_cntl;
if (ASIC_IS_DCE4(rdev)) { if (ASIC_IS_DCE4(rdev)) {
switch (radeon_crtc->pll_id) { switch (pll_id) {
case ATOM_PPLL1: case ATOM_PPLL1:
ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL); ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
ss_cntl &= ~EVERGREEN_PxPLL_SS_EN; ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
...@@ -379,7 +376,7 @@ static void atombios_disable_ss(struct drm_crtc *crtc) ...@@ -379,7 +376,7 @@ static void atombios_disable_ss(struct drm_crtc *crtc)
return; return;
} }
} else if (ASIC_IS_AVIVO(rdev)) { } else if (ASIC_IS_AVIVO(rdev)) {
switch (radeon_crtc->pll_id) { switch (pll_id) {
case ATOM_PPLL1: case ATOM_PPLL1:
ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
ss_cntl &= ~1; ss_cntl &= ~1;
...@@ -406,13 +403,11 @@ union atom_enable_ss { ...@@ -406,13 +403,11 @@ union atom_enable_ss {
ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3; ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
}; };
static void atombios_crtc_program_ss(struct drm_crtc *crtc, static void atombios_crtc_program_ss(struct radeon_device *rdev,
int enable, int enable,
int pll_id, int pll_id,
struct radeon_atom_ss *ss) struct radeon_atom_ss *ss)
{ {
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
union atom_enable_ss args; union atom_enable_ss args;
...@@ -479,7 +474,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, ...@@ -479,7 +474,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
} else if (ASIC_IS_AVIVO(rdev)) { } else if (ASIC_IS_AVIVO(rdev)) {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) { (ss->type & ATOM_EXTERNAL_SS_MASK)) {
atombios_disable_ss(crtc); atombios_disable_ss(rdev, pll_id);
return; return;
} }
args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
...@@ -491,7 +486,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc, ...@@ -491,7 +486,7 @@ static void atombios_crtc_program_ss(struct drm_crtc *crtc,
} else { } else {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) || if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) { (ss->type & ATOM_EXTERNAL_SS_MASK)) {
atombios_disable_ss(crtc); atombios_disable_ss(rdev, pll_id);
return; return;
} }
args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage); args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
...@@ -523,6 +518,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -523,6 +518,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
int encoder_mode = 0; int encoder_mode = 0;
u32 dp_clock = mode->clock; u32 dp_clock = mode->clock;
int bpc = 8; int bpc = 8;
bool is_duallink = false;
/* reset the pll flags */ /* reset the pll flags */
pll->flags = 0; pll->flags = 0;
...@@ -557,6 +553,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -557,6 +553,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
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);
if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
(radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) { (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
if (connector) { if (connector) {
...@@ -652,7 +649,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -652,7 +649,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (dig->coherent_mode) if (dig->coherent_mode)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE; DISPPLL_CONFIG_COHERENT_MODE;
if (mode->clock > 165000) if (is_duallink)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_DUAL_LINK; DISPPLL_CONFIG_DUAL_LINK;
} }
...@@ -702,11 +699,9 @@ union set_pixel_clock { ...@@ -702,11 +699,9 @@ union set_pixel_clock {
/* on DCE5, make sure the voltage is high enough to support the /* on DCE5, make sure the voltage is high enough to support the
* required disp clk. * required disp clk.
*/ */
static void atombios_crtc_set_dcpll(struct drm_crtc *crtc, static void atombios_crtc_set_dcpll(struct radeon_device *rdev,
u32 dispclk) u32 dispclk)
{ {
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
u8 frev, crev; u8 frev, crev;
int index; int index;
union set_pixel_clock args; union set_pixel_clock args;
...@@ -996,7 +991,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -996,7 +991,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, radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
&ref_div, &post_div); &ref_div, &post_div);
atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss); atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
encoder_mode, radeon_encoder->encoder_id, mode->clock, encoder_mode, radeon_encoder->encoder_id, mode->clock,
...@@ -1019,7 +1014,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -1019,7 +1014,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
ss.step = step_size; ss.step = step_size;
} }
atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss); atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
} }
} }
...@@ -1494,6 +1489,24 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) ...@@ -1494,6 +1489,24 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
} }
void radeon_atom_dcpll_init(struct radeon_device *rdev)
{
/* always set DCPLL */
if (ASIC_IS_DCE4(rdev)) {
struct radeon_atom_ss ss;
bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_SS_ON_DCPLL,
rdev->clock.default_dispclk);
if (ss_enabled)
atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
/* XXX: DCE5, make sure voltage, dispclk is high enough */
atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk);
if (ss_enabled)
atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
}
}
int atombios_crtc_mode_set(struct drm_crtc *crtc, int atombios_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode, struct drm_display_mode *adjusted_mode,
...@@ -1515,19 +1528,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, ...@@ -1515,19 +1528,6 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
} }
} }
/* always set DCPLL */
if (ASIC_IS_DCE4(rdev)) {
struct radeon_atom_ss ss;
bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
ASIC_INTERNAL_SS_ON_DCPLL,
rdev->clock.default_dispclk);
if (ss_enabled)
atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss);
/* XXX: DCE5, make sure voltage, dispclk is high enough */
atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk);
if (ss_enabled)
atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss);
}
atombios_crtc_set_pll(crtc, adjusted_mode); atombios_crtc_set_pll(crtc, adjusted_mode);
if (ASIC_IS_DCE4(rdev)) if (ASIC_IS_DCE4(rdev))
......
...@@ -549,7 +549,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) ...@@ -549,7 +549,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
return false; return false;
} }
static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_connector *connector) struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -558,7 +558,7 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, ...@@ -558,7 +558,7 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
if (!ASIC_IS_DCE4(rdev)) if (!ASIC_IS_DCE4(rdev))
return; return panel_mode;
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG) ENCODER_OBJECT_ID_NUTMEG)
...@@ -572,14 +572,7 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, ...@@ -572,14 +572,7 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
} }
atombios_dig_encoder_setup(encoder, return panel_mode;
ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
panel_mode);
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
(panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
}
} }
void radeon_dp_set_link_config(struct drm_connector *connector, void radeon_dp_set_link_config(struct drm_connector *connector,
...@@ -717,6 +710,8 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) ...@@ -717,6 +710,8 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
{ {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
u8 tmp; u8 tmp;
/* power up the sink */ /* power up the sink */
...@@ -732,7 +727,10 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) ...@@ -732,7 +727,10 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
radeon_write_dpcd_reg(dp_info->radeon_connector, radeon_write_dpcd_reg(dp_info->radeon_connector,
DP_DOWNSPREAD_CTRL, 0); DP_DOWNSPREAD_CTRL, 0);
radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector); if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
(dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
}
/* set the lane count on the sink */ /* set the lane count on the sink */
tmp = dp_info->dp_lane_count; tmp = dp_info->dp_lane_count;
......
This diff is collapsed.
...@@ -1455,6 +1455,7 @@ int evergreen_cp_resume(struct radeon_device *rdev) ...@@ -1455,6 +1455,7 @@ int evergreen_cp_resume(struct radeon_device *rdev)
#endif #endif
WREG32(CP_RB_CNTL, tmp); WREG32(CP_RB_CNTL, tmp);
WREG32(CP_SEM_WAIT_TIMER, 0x0); WREG32(CP_SEM_WAIT_TIMER, 0x0);
WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */ /* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0); WREG32(CP_RB_WPTR_DELAY, 0);
......
...@@ -108,6 +108,7 @@ ...@@ -108,6 +108,7 @@
#define CP_RB_WPTR_ADDR_HI 0xC11C #define CP_RB_WPTR_ADDR_HI 0xC11C
#define CP_RB_WPTR_DELAY 0x8704 #define CP_RB_WPTR_DELAY 0x8704
#define CP_SEM_WAIT_TIMER 0x85BC #define CP_SEM_WAIT_TIMER 0x85BC
#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_DEBUG 0xC1FC #define CP_DEBUG 0xC1FC
......
...@@ -1219,6 +1219,7 @@ int cayman_cp_resume(struct radeon_device *rdev) ...@@ -1219,6 +1219,7 @@ int cayman_cp_resume(struct radeon_device *rdev)
RREG32(GRBM_SOFT_RESET); RREG32(GRBM_SOFT_RESET);
WREG32(CP_SEM_WAIT_TIMER, 0x0); WREG32(CP_SEM_WAIT_TIMER, 0x0);
WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */ /* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0); WREG32(CP_RB_WPTR_DELAY, 0);
......
...@@ -222,6 +222,7 @@ ...@@ -222,6 +222,7 @@
#define SCRATCH_UMSK 0x8540 #define SCRATCH_UMSK 0x8540
#define SCRATCH_ADDR 0x8544 #define SCRATCH_ADDR 0x8544
#define CP_SEM_WAIT_TIMER 0x85BC #define CP_SEM_WAIT_TIMER 0x85BC
#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_COHER_CNTL2 0x85E8 #define CP_COHER_CNTL2 0x85E8
#define CP_ME_CNTL 0x86D8 #define CP_ME_CNTL 0x86D8
#define CP_ME_HALT (1 << 28) #define CP_ME_HALT (1 << 28)
......
...@@ -156,6 +156,47 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) ...@@ -156,6 +156,47 @@ static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len)
bool radeon_get_bios(struct radeon_device *rdev); bool radeon_get_bios(struct radeon_device *rdev);
/*
* Mutex which allows recursive locking from the same process.
*/
struct radeon_mutex {
struct mutex mutex;
struct task_struct *owner;
int level;
};
static inline void radeon_mutex_init(struct radeon_mutex *mutex)
{
mutex_init(&mutex->mutex);
mutex->owner = NULL;
mutex->level = 0;
}
static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
{
if (mutex_trylock(&mutex->mutex)) {
/* The mutex was unlocked before, so it's ours now */
mutex->owner = current;
} else if (mutex->owner != current) {
/* Another process locked the mutex, take it */
mutex_lock(&mutex->mutex);
mutex->owner = current;
}
/* Otherwise the mutex was already locked by this process */
mutex->level++;
}
static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
{
if (--mutex->level > 0)
return;
mutex->owner = NULL;
mutex_unlock(&mutex->mutex);
}
/* /*
* Dummy page * Dummy page
*/ */
...@@ -598,7 +639,7 @@ struct radeon_ib { ...@@ -598,7 +639,7 @@ struct radeon_ib {
* mutex protects scheduled_ibs, ready, alloc_bm * mutex protects scheduled_ibs, ready, alloc_bm
*/ */
struct radeon_ib_pool { struct radeon_ib_pool {
struct mutex mutex; struct radeon_mutex mutex;
struct radeon_sa_manager sa_manager; struct radeon_sa_manager sa_manager;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready; bool ready;
...@@ -1354,47 +1395,6 @@ struct r600_vram_scratch { ...@@ -1354,47 +1395,6 @@ struct r600_vram_scratch {
}; };
/*
* Mutex which allows recursive locking from the same process.
*/
struct radeon_mutex {
struct mutex mutex;
struct task_struct *owner;
int level;
};
static inline void radeon_mutex_init(struct radeon_mutex *mutex)
{
mutex_init(&mutex->mutex);
mutex->owner = NULL;
mutex->level = 0;
}
static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
{
if (mutex_trylock(&mutex->mutex)) {
/* The mutex was unlocked before, so it's ours now */
mutex->owner = current;
} else if (mutex->owner != current) {
/* Another process locked the mutex, take it */
mutex_lock(&mutex->mutex);
mutex->owner = current;
}
/* Otherwise the mutex was already locked by this process */
mutex->level++;
}
static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
{
if (--mutex->level > 0)
return;
mutex->owner = NULL;
mutex_unlock(&mutex->mutex);
}
/* /*
* Core structure, functions and helpers. * Core structure, functions and helpers.
*/ */
......
...@@ -58,9 +58,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, ...@@ -58,9 +58,9 @@ static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
} }
obj = (union acpi_object *)buffer.pointer; obj = (union acpi_object *)buffer.pointer;
memcpy(bios+offset, obj->buffer.pointer, len); memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
kfree(buffer.pointer); kfree(buffer.pointer);
return len; return obj->buffer.length;
} }
bool radeon_atrm_supported(struct pci_dev *pdev) bool radeon_atrm_supported(struct pci_dev *pdev)
......
...@@ -120,7 +120,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) ...@@ -120,7 +120,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
ret = radeon_atrm_get_bios_chunk(rdev->bios, ret = radeon_atrm_get_bios_chunk(rdev->bios,
(i * ATRM_BIOS_PAGE), (i * ATRM_BIOS_PAGE),
ATRM_BIOS_PAGE); ATRM_BIOS_PAGE);
if (ret <= 0) if (ret < ATRM_BIOS_PAGE)
break; break;
} }
......
...@@ -720,7 +720,7 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -720,7 +720,7 @@ int radeon_device_init(struct radeon_device *rdev,
/* mutex initialization are all done here so we /* mutex initialization are all done here so we
* can recall function without having locking issues */ * can recall function without having locking issues */
radeon_mutex_init(&rdev->cs_mutex); radeon_mutex_init(&rdev->cs_mutex);
mutex_init(&rdev->ib_pool.mutex); radeon_mutex_init(&rdev->ib_pool.mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i) for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(&rdev->ring[i].mutex); mutex_init(&rdev->ring[i].mutex);
mutex_init(&rdev->dc_hw_i2c_mutex); mutex_init(&rdev->dc_hw_i2c_mutex);
...@@ -959,9 +959,11 @@ int radeon_resume_kms(struct drm_device *dev) ...@@ -959,9 +959,11 @@ int radeon_resume_kms(struct drm_device *dev)
radeon_fbdev_set_suspend(rdev, 0); radeon_fbdev_set_suspend(rdev, 0);
console_unlock(); console_unlock();
/* init dig PHYs */ /* init dig PHYs, disp eng pll */
if (rdev->is_atom_bios) if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev); radeon_atom_encoder_init(rdev);
radeon_atom_dcpll_init(rdev);
}
/* reset hpd state */ /* reset hpd state */
radeon_hpd_init(rdev); radeon_hpd_init(rdev);
/* blat the mode back in */ /* blat the mode back in */
......
...@@ -1305,9 +1305,11 @@ int radeon_modeset_init(struct radeon_device *rdev) ...@@ -1305,9 +1305,11 @@ int radeon_modeset_init(struct radeon_device *rdev)
return ret; return ret;
} }
/* init dig PHYs */ /* init dig PHYs, disp eng pll */
if (rdev->is_atom_bios) if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev); radeon_atom_encoder_init(rdev);
radeon_atom_dcpll_init(rdev);
}
/* initialize hpd */ /* initialize hpd */
radeon_hpd_init(rdev); radeon_hpd_init(rdev);
......
...@@ -202,6 +202,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder) ...@@ -202,6 +202,22 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
return NULL; return NULL;
} }
struct drm_connector *
radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
radeon_connector = to_radeon_connector(connector);
if (radeon_encoder->devices & radeon_connector->devices)
return connector;
}
return NULL;
}
struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder) struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -288,3 +304,64 @@ void radeon_panel_mode_fixup(struct drm_encoder *encoder, ...@@ -288,3 +304,64 @@ void radeon_panel_mode_fixup(struct drm_encoder *encoder,
} }
bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
u32 pixel_clock)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *dig_connector;
connector = radeon_get_connector_for_encoder(encoder);
/* if we don't have an active device yet, just use one of
* the connectors tied to the encoder.
*/
if (!connector)
connector = radeon_get_connector_for_encoder_init(encoder);
radeon_connector = to_radeon_connector(connector);
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB:
if (radeon_connector->use_digital) {
/* HDMI 1.3 supports up to 340 Mhz over single link */
if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
if (pixel_clock > 340000)
return true;
else
return false;
} else {
if (pixel_clock > 165000)
return true;
else
return false;
}
} else
return false;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_DisplayPort:
dig_connector = radeon_connector->con_priv;
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
return false;
else {
/* HDMI 1.3 supports up to 340 Mhz over single link */
if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
if (pixel_clock > 340000)
return true;
else
return false;
} else {
if (pixel_clock > 165000)
return true;
else
return false;
}
}
default:
return false;
}
}
...@@ -135,6 +135,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev) ...@@ -135,6 +135,12 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
(rdev->pdev->subsystem_device == 0x30c2)) (rdev->pdev->subsystem_device == 0x30c2))
return true; return true;
/* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) &&
(rdev->pdev->subsystem_device == 0x01fc))
return true;
/* Dell RS690 only seems to work with MSIs. */ /* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) && if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) && (rdev->pdev->subsystem_vendor == 0x1028) &&
......
...@@ -362,6 +362,7 @@ struct radeon_encoder_atom_dig { ...@@ -362,6 +362,7 @@ struct radeon_encoder_atom_dig {
struct backlight_device *bl_dev; struct backlight_device *bl_dev;
int dpms_mode; int dpms_mode;
uint8_t backlight_level; uint8_t backlight_level;
int panel_mode;
}; };
struct radeon_encoder_atom_dac { struct radeon_encoder_atom_dac {
...@@ -466,6 +467,10 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); ...@@ -466,6 +467,10 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev);
extern struct drm_connector * extern struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder *encoder); radeon_get_connector_for_encoder(struct drm_encoder *encoder);
extern struct drm_connector *
radeon_get_connector_for_encoder_init(struct drm_encoder *encoder);
extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
u32 pixel_clock);
extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder); extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector); extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
...@@ -482,8 +487,11 @@ extern void radeon_dp_link_train(struct drm_encoder *encoder, ...@@ -482,8 +487,11 @@ extern void radeon_dp_link_train(struct drm_encoder *encoder,
extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_connector *connector);
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode); extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
extern void radeon_atom_encoder_init(struct radeon_device *rdev); extern void radeon_atom_encoder_init(struct radeon_device *rdev);
extern void radeon_atom_dcpll_init(struct radeon_device *rdev);
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
int action, uint8_t lane_num, int action, uint8_t lane_num,
uint8_t lane_set); uint8_t lane_set);
......
...@@ -109,12 +109,12 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, ...@@ -109,12 +109,12 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
return r; return r;
} }
mutex_lock(&rdev->ib_pool.mutex); radeon_mutex_lock(&rdev->ib_pool.mutex);
idx = rdev->ib_pool.head_id; idx = rdev->ib_pool.head_id;
retry: retry:
if (cretry > 5) { if (cretry > 5) {
dev_err(rdev->dev, "failed to get an ib after 5 retry\n"); dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence); radeon_fence_unref(&fence);
return -ENOMEM; return -ENOMEM;
} }
...@@ -139,7 +139,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, ...@@ -139,7 +139,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
*/ */
rdev->ib_pool.head_id = (1 + idx); rdev->ib_pool.head_id = (1 + idx);
rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1); rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0; return 0;
} }
} }
...@@ -158,7 +158,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, ...@@ -158,7 +158,7 @@ int radeon_ib_get(struct radeon_device *rdev, int ring,
} }
idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1); idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
} }
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence); radeon_fence_unref(&fence);
return r; return r;
} }
...@@ -171,12 +171,12 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) ...@@ -171,12 +171,12 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
if (tmp == NULL) { if (tmp == NULL) {
return; return;
} }
mutex_lock(&rdev->ib_pool.mutex); radeon_mutex_lock(&rdev->ib_pool.mutex);
if (tmp->fence && !tmp->fence->emitted) { if (tmp->fence && !tmp->fence->emitted) {
radeon_sa_bo_free(rdev, &tmp->sa_bo); radeon_sa_bo_free(rdev, &tmp->sa_bo);
radeon_fence_unref(&tmp->fence); radeon_fence_unref(&tmp->fence);
} }
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
} }
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
...@@ -204,22 +204,25 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -204,22 +204,25 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
int radeon_ib_pool_init(struct radeon_device *rdev) int radeon_ib_pool_init(struct radeon_device *rdev)
{ {
struct radeon_sa_manager tmp;
int i, r; int i, r;
mutex_lock(&rdev->ib_pool.mutex); r = radeon_sa_bo_manager_init(rdev, &tmp,
if (rdev->ib_pool.ready) {
mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
r = radeon_sa_bo_manager_init(rdev, &rdev->ib_pool.sa_manager,
RADEON_IB_POOL_SIZE*64*1024, RADEON_IB_POOL_SIZE*64*1024,
RADEON_GEM_DOMAIN_GTT); RADEON_GEM_DOMAIN_GTT);
if (r) { if (r) {
mutex_unlock(&rdev->ib_pool.mutex);
return r; return r;
} }
radeon_mutex_lock(&rdev->ib_pool.mutex);
if (rdev->ib_pool.ready) {
radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_sa_bo_manager_fini(rdev, &tmp);
return 0;
}
rdev->ib_pool.sa_manager = tmp;
INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo);
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
rdev->ib_pool.ibs[i].fence = NULL; rdev->ib_pool.ibs[i].fence = NULL;
rdev->ib_pool.ibs[i].idx = i; rdev->ib_pool.ibs[i].idx = i;
...@@ -236,7 +239,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev) ...@@ -236,7 +239,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
if (radeon_debugfs_ring_init(rdev)) { if (radeon_debugfs_ring_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for rings !\n"); DRM_ERROR("Failed to register debugfs file for rings !\n");
} }
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0; return 0;
} }
...@@ -244,7 +247,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) ...@@ -244,7 +247,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
{ {
unsigned i; unsigned i;
mutex_lock(&rdev->ib_pool.mutex); radeon_mutex_lock(&rdev->ib_pool.mutex);
if (rdev->ib_pool.ready) { if (rdev->ib_pool.ready) {
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo); radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
...@@ -253,7 +256,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) ...@@ -253,7 +256,7 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager); radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
rdev->ib_pool.ready = false; rdev->ib_pool.ready = false;
} }
mutex_unlock(&rdev->ib_pool.mutex); radeon_mutex_unlock(&rdev->ib_pool.mutex);
} }
int radeon_ib_pool_start(struct radeon_device *rdev) int radeon_ib_pool_start(struct radeon_device *rdev)
......
...@@ -40,7 +40,6 @@ static struct pci_device_id pciidlist[] = { ...@@ -40,7 +40,6 @@ static struct pci_device_id pciidlist[] = {
static int sis_driver_load(struct drm_device *dev, unsigned long chipset) static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
{ {
drm_sis_private_t *dev_priv; drm_sis_private_t *dev_priv;
int ret;
dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
if (dev_priv == NULL) if (dev_priv == NULL)
...@@ -50,7 +49,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) ...@@ -50,7 +49,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->chipset = chipset; dev_priv->chipset = chipset;
idr_init(&dev->object_name_idr); idr_init(&dev->object_name_idr);
return ret; return 0;
} }
static int sis_driver_unload(struct drm_device *dev) static int sis_driver_unload(struct drm_device *dev)
......
...@@ -404,6 +404,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, ...@@ -404,6 +404,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
} }
} }
if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, mem);
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem); ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem);
...@@ -413,11 +416,17 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, ...@@ -413,11 +416,17 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
else else
ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem); ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem);
if (ret) if (ret) {
goto out_err; if (bdev->driver->move_notify) {
struct ttm_mem_reg tmp_mem = *mem;
if (bdev->driver->move_notify) *mem = bo->mem;
bo->mem = tmp_mem;
bdev->driver->move_notify(bo, mem); bdev->driver->move_notify(bo, mem);
bo->mem = *mem;
}
goto out_err;
}
moved: moved:
if (bo->evicted) { if (bo->evicted) {
......
...@@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data, ...@@ -1328,6 +1328,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_authmagic(struct drm_device *dev, void *data, extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
/* Cache management (drm_cache.c) */ /* Cache management (drm_cache.c) */
void drm_clflush_pages(struct page *pages[], unsigned long num_pages); void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
......
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