Commit 83dbb15e 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: (40 commits)
  vmwgfx: Snoop DMA transfers with non-covering sizes
  vmwgfx: Move the prefered mode first in the list
  vmwgfx: Unreference surface on cursor error path
  vmwgfx: Free prefered mode on error path
  vmwgfx: Use pointer return error codes
  vmwgfx: Fix hw cursor position
  vmwgfx: Infrastructure for explicit placement
  vmwgfx: Make the preferred autofit mode have a 60Hz vrefresh
  vmwgfx: Remove screen object active list
  vmwgfx: Screen object cleanups
  drm/radeon/kms: consolidate GART code, fix segfault after GPU lockup V2
  drm/radeon/kms: don't poll forever if MC GDDR link training fails
  drm/radeon/kms: fix DP setup on TRAVIS bridges
  drm/radeon/kms: set HPD polarity in hpd_init()
  drm/radeon/kms: add MSI module parameter
  drm/radeon/kms: Add MSI quirk for Dell RS690
  drm/radeon/kms: Add MSI quirk for HP RS690
  drm/radeon/kms: split MSI check into a separate function
  vmwgfx: Reinstate the update_layout ioctl
  drm/radeon/kms: always do extended edid probe
  ...
parents 6e6bc679 2ac86371
...@@ -163,6 +163,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = ...@@ -163,6 +163,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
{ DRM_MODE_CONNECTOR_TV, "TV", 0 }, { DRM_MODE_CONNECTOR_TV, "TV", 0 },
{ DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
}; };
static struct drm_prop_enum_list drm_encoder_enum_list[] = static struct drm_prop_enum_list drm_encoder_enum_list[] =
...@@ -171,6 +172,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] = ...@@ -171,6 +172,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
{ DRM_MODE_ENCODER_TMDS, "TMDS" }, { DRM_MODE_ENCODER_TMDS, "TMDS" },
{ DRM_MODE_ENCODER_LVDS, "LVDS" }, { DRM_MODE_ENCODER_LVDS, "LVDS" },
{ DRM_MODE_ENCODER_TVDAC, "TV" }, { DRM_MODE_ENCODER_TVDAC, "TV" },
{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
}; };
char *drm_get_encoder_name(struct drm_encoder *encoder) char *drm_get_encoder_name(struct drm_encoder *encoder)
...@@ -464,8 +466,10 @@ void drm_connector_init(struct drm_device *dev, ...@@ -464,8 +466,10 @@ void drm_connector_init(struct drm_device *dev,
list_add_tail(&connector->head, &dev->mode_config.connector_list); list_add_tail(&connector->head, &dev->mode_config.connector_list);
dev->mode_config.num_connector++; dev->mode_config.num_connector++;
if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.edid_property, 0); dev->mode_config.edid_property,
0);
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.dpms_property, 0); dev->mode_config.dpms_property, 0);
......
...@@ -70,7 +70,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ ...@@ -70,7 +70,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
radeon_trace_points.o ni.o cayman_blit_shaders.o radeon_trace_points.o ni.o cayman_blit_shaders.o atombios_encoders.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
......
...@@ -558,7 +558,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -558,7 +558,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
bpc = connector->display_info.bpc; bpc = connector->display_info.bpc;
encoder_mode = atombios_get_encoder_mode(encoder); encoder_mode = atombios_get_encoder_mode(encoder);
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_is_dp_bridge(encoder)) { (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
if (connector) { if (connector) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector = struct radeon_connector_atom_dig *dig_connector =
...@@ -638,20 +638,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -638,20 +638,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
if (ss_enabled && ss->percentage) if (ss_enabled && ss->percentage)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_SS_ENABLE; DISPPLL_CONFIG_SS_ENABLE;
if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT) || if (ENCODER_MODE_IS_DP(encoder_mode)) {
radeon_encoder_is_dp_bridge(encoder)) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
if (encoder_mode == ATOM_ENCODER_MODE_DP) {
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE; DISPPLL_CONFIG_COHERENT_MODE;
/* 16200 or 27000 */ /* 16200 or 27000 */
args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
} else { } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
/* deep color support */ /* deep color support */
args.v3.sInput.usPixelClock = args.v3.sInput.usPixelClock =
cpu_to_le16((mode->clock * bpc / 8) / 10); cpu_to_le16((mode->clock * bpc / 8) / 10);
}
if (dig->coherent_mode) if (dig->coherent_mode)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE; DISPPLL_CONFIG_COHERENT_MODE;
...@@ -659,23 +656,11 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -659,23 +656,11 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_DUAL_LINK; DISPPLL_CONFIG_DUAL_LINK;
} }
} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
if (encoder_mode == ATOM_ENCODER_MODE_DP) { ENCODER_OBJECT_ID_NONE)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucExtTransmitterID =
DISPPLL_CONFIG_COHERENT_MODE; radeon_encoder_get_dp_bridge_encoder_id(encoder);
/* 16200 or 27000 */ else
args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
} else if (encoder_mode != ATOM_ENCODER_MODE_LVDS) {
if (mode->clock > 165000)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_DUAL_LINK;
}
}
if (radeon_encoder_is_dp_bridge(encoder)) {
struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
} else
args.v3.sInput.ucExtTransmitterID = 0; args.v3.sInput.ucExtTransmitterID = 0;
atom_execute_table(rdev->mode_info.atom_context, atom_execute_table(rdev->mode_info.atom_context,
...@@ -945,6 +930,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -945,6 +930,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
bpc = 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: case ATOM_ENCODER_MODE_DP:
/* DP/eDP */ /* DP/eDP */
dp_clock = dig_connector->dp_clock / 10; dp_clock = dig_connector->dp_clock / 10;
...@@ -1450,7 +1436,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) ...@@ -1450,7 +1436,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
* PPLL/DCPLL programming and only program the DP DTO for the * PPLL/DCPLL programming and only program the DP DTO for the
* crtc virtual pixel clock. * crtc virtual pixel clock.
*/ */
if (atombios_get_encoder_mode(test_encoder) == ATOM_ENCODER_MODE_DP) { if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk)
return ATOM_PPLL_INVALID; return ATOM_PPLL_INVALID;
} }
......
...@@ -482,7 +482,8 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, ...@@ -482,7 +482,8 @@ static int radeon_dp_get_dp_link_clock(struct drm_connector *connector,
int bpp = convert_bpc_to_bpp(connector->display_info.bpc); int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
int lane_num, max_pix_clock; int lane_num, max_pix_clock;
if (radeon_connector_encoder_is_dp_bridge(connector)) if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG)
return 270000; return 270000;
lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
...@@ -553,17 +554,32 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, ...@@ -553,17 +554,32 @@ static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
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;
if (radeon_connector_encoder_is_dp_bridge(connector)) if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG)
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 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) {
u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
atombios_dig_encoder_setup(encoder, atombios_dig_encoder_setup(encoder,
ATOM_ENCODER_CMD_SETUP_PANEL_MODE, ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
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,
......
This diff is collapsed.
...@@ -353,6 +353,7 @@ void evergreen_hpd_init(struct radeon_device *rdev) ...@@ -353,6 +353,7 @@ void evergreen_hpd_init(struct radeon_device *rdev)
default: default:
break; break;
} }
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
} }
if (rdev->irq.installed) if (rdev->irq.installed)
evergreen_irq_set(rdev); evergreen_irq_set(rdev);
...@@ -893,7 +894,7 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) ...@@ -893,7 +894,7 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
u32 tmp; u32 tmp;
int r; int r;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -945,7 +946,6 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) ...@@ -945,7 +946,6 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
void evergreen_pcie_gart_disable(struct radeon_device *rdev) void evergreen_pcie_gart_disable(struct radeon_device *rdev)
{ {
u32 tmp; u32 tmp;
int r;
/* Disable all tables */ /* Disable all tables */
WREG32(VM_CONTEXT0_CNTL, 0); WREG32(VM_CONTEXT0_CNTL, 0);
...@@ -965,14 +965,7 @@ void evergreen_pcie_gart_disable(struct radeon_device *rdev) ...@@ -965,14 +965,7 @@ void evergreen_pcie_gart_disable(struct radeon_device *rdev)
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void evergreen_pcie_gart_fini(struct radeon_device *rdev) void evergreen_pcie_gart_fini(struct radeon_device *rdev)
...@@ -3031,6 +3024,10 @@ static int evergreen_startup(struct radeon_device *rdev) ...@@ -3031,6 +3024,10 @@ static int evergreen_startup(struct radeon_device *rdev)
} }
} }
r = r600_vram_scratch_init(rdev);
if (r)
return r;
evergreen_mc_program(rdev); evergreen_mc_program(rdev);
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
evergreen_agp_enable(rdev); evergreen_agp_enable(rdev);
...@@ -3235,6 +3232,7 @@ void evergreen_fini(struct radeon_device *rdev) ...@@ -3235,6 +3232,7 @@ void evergreen_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
evergreen_pcie_gart_fini(rdev); evergreen_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
radeon_agp_fini(rdev); radeon_agp_fini(rdev);
......
...@@ -94,6 +94,15 @@ cp_set_surface_sync(struct radeon_device *rdev, ...@@ -94,6 +94,15 @@ cp_set_surface_sync(struct radeon_device *rdev,
else else
cp_coher_size = ((size + 255) >> 8); cp_coher_size = ((size + 255) >> 8);
if (rdev->family >= CHIP_CAYMAN) {
/* CP_COHER_CNTL2 has to be set manually when submitting a surface_sync
* to the RB directly. For IBs, the CP programs this as part of the
* surface_sync packet.
*/
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(rdev, (0x85e8 - PACKET3_SET_CONFIG_REG_START) >> 2);
radeon_ring_write(rdev, 0); /* CP_COHER_CNTL2 */
}
radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3)); radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
radeon_ring_write(rdev, sync_type); radeon_ring_write(rdev, sync_type);
radeon_ring_write(rdev, cp_coher_size); radeon_ring_write(rdev, cp_coher_size);
...@@ -174,7 +183,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) ...@@ -174,7 +183,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
static void static void
set_tex_resource(struct radeon_device *rdev, set_tex_resource(struct radeon_device *rdev,
int format, int w, int h, int pitch, int format, int w, int h, int pitch,
u64 gpu_addr) u64 gpu_addr, u32 size)
{ {
u32 sq_tex_resource_word0, sq_tex_resource_word1; u32 sq_tex_resource_word0, sq_tex_resource_word1;
u32 sq_tex_resource_word4, sq_tex_resource_word7; u32 sq_tex_resource_word4, sq_tex_resource_word7;
...@@ -196,6 +205,9 @@ set_tex_resource(struct radeon_device *rdev, ...@@ -196,6 +205,9 @@ set_tex_resource(struct radeon_device *rdev,
sq_tex_resource_word7 = format | sq_tex_resource_word7 = format |
S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE); S__SQ_CONSTANT_TYPE(SQ_TEX_VTX_VALID_TEXTURE);
cp_set_surface_sync(rdev,
PACKET3_TC_ACTION_ENA, size, gpu_addr);
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8)); radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 8));
radeon_ring_write(rdev, 0); radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, sq_tex_resource_word0); radeon_ring_write(rdev, sq_tex_resource_word0);
...@@ -613,11 +625,13 @@ int evergreen_blit_init(struct radeon_device *rdev) ...@@ -613,11 +625,13 @@ int evergreen_blit_init(struct radeon_device *rdev)
rdev->r600_blit.primitives.set_default_state = set_default_state; rdev->r600_blit.primitives.set_default_state = set_default_state;
rdev->r600_blit.ring_size_common = 55; /* shaders + def state */ rdev->r600_blit.ring_size_common = 55; /* shaders + def state */
rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */ rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
rdev->r600_blit.ring_size_common += 5; /* done copy */ rdev->r600_blit.ring_size_common += 5; /* done copy */
rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */ rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
rdev->r600_blit.ring_size_per_loop = 74; rdev->r600_blit.ring_size_per_loop = 74;
if (rdev->family >= CHIP_CAYMAN)
rdev->r600_blit.ring_size_per_loop += 9; /* additional DWs for surface sync */
rdev->r600_blit.max_dim = 16384; rdev->r600_blit.max_dim = 16384;
......
...@@ -262,8 +262,11 @@ int ni_mc_load_microcode(struct radeon_device *rdev) ...@@ -262,8 +262,11 @@ int ni_mc_load_microcode(struct radeon_device *rdev)
WREG32(MC_SEQ_SUP_CNTL, 0x00000001); WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
/* wait for training to complete */ /* wait for training to complete */
while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)) for (i = 0; i < rdev->usec_timeout; i++) {
udelay(10); if (RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD)
break;
udelay(1);
}
if (running) if (running)
WREG32(MC_SHARED_BLACKOUT_CNTL, blackout); WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
...@@ -933,7 +936,7 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) ...@@ -933,7 +936,7 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -978,8 +981,6 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev) ...@@ -978,8 +981,6 @@ int cayman_pcie_gart_enable(struct radeon_device *rdev)
void cayman_pcie_gart_disable(struct radeon_device *rdev) void cayman_pcie_gart_disable(struct radeon_device *rdev)
{ {
int r;
/* Disable all tables */ /* Disable all tables */
WREG32(VM_CONTEXT0_CNTL, 0); WREG32(VM_CONTEXT0_CNTL, 0);
WREG32(VM_CONTEXT1_CNTL, 0); WREG32(VM_CONTEXT1_CNTL, 0);
...@@ -995,14 +996,7 @@ void cayman_pcie_gart_disable(struct radeon_device *rdev) ...@@ -995,14 +996,7 @@ void cayman_pcie_gart_disable(struct radeon_device *rdev)
WREG32(VM_L2_CNTL2, 0); WREG32(VM_L2_CNTL2, 0);
WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY | WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
L2_CACHE_BIGK_FRAGMENT_SIZE(6)); L2_CACHE_BIGK_FRAGMENT_SIZE(6));
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void cayman_pcie_gart_fini(struct radeon_device *rdev) void cayman_pcie_gart_fini(struct radeon_device *rdev)
...@@ -1362,6 +1356,10 @@ static int cayman_startup(struct radeon_device *rdev) ...@@ -1362,6 +1356,10 @@ static int cayman_startup(struct radeon_device *rdev)
return r; return r;
} }
r = r600_vram_scratch_init(rdev);
if (r)
return r;
evergreen_mc_program(rdev); evergreen_mc_program(rdev);
r = cayman_pcie_gart_enable(rdev); r = cayman_pcie_gart_enable(rdev);
if (r) if (r)
...@@ -1557,6 +1555,7 @@ void cayman_fini(struct radeon_device *rdev) ...@@ -1557,6 +1555,7 @@ void cayman_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
cayman_pcie_gart_fini(rdev); cayman_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
radeon_bo_fini(rdev); radeon_bo_fini(rdev);
......
...@@ -537,6 +537,7 @@ void r100_hpd_init(struct radeon_device *rdev) ...@@ -537,6 +537,7 @@ void r100_hpd_init(struct radeon_device *rdev)
default: default:
break; break;
} }
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
} }
if (rdev->irq.installed) if (rdev->irq.installed)
r100_irq_set(rdev); r100_irq_set(rdev);
...@@ -577,7 +578,7 @@ int r100_pci_gart_init(struct radeon_device *rdev) ...@@ -577,7 +578,7 @@ int r100_pci_gart_init(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.ram.ptr) { if (rdev->gart.ptr) {
WARN(1, "R100 PCI GART already initialized\n"); WARN(1, "R100 PCI GART already initialized\n");
return 0; return 0;
} }
...@@ -636,10 +637,12 @@ void r100_pci_gart_disable(struct radeon_device *rdev) ...@@ -636,10 +637,12 @@ void r100_pci_gart_disable(struct radeon_device *rdev)
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
u32 *gtt = rdev->gart.ptr;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
} }
rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr)); gtt[i] = cpu_to_le32(lower_32_bits(addr));
return 0; return 0;
} }
......
...@@ -74,7 +74,7 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) ...@@ -74,7 +74,7 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; void __iomem *ptr = rdev->gart.ptr;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
...@@ -93,7 +93,7 @@ int rv370_pcie_gart_init(struct radeon_device *rdev) ...@@ -93,7 +93,7 @@ int rv370_pcie_gart_init(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj) { if (rdev->gart.robj) {
WARN(1, "RV370 PCIE GART already initialized\n"); WARN(1, "RV370 PCIE GART already initialized\n");
return 0; return 0;
} }
...@@ -116,7 +116,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) ...@@ -116,7 +116,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
uint32_t tmp; uint32_t tmp;
int r; int r;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -154,7 +154,6 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) ...@@ -154,7 +154,6 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
void rv370_pcie_gart_disable(struct radeon_device *rdev) void rv370_pcie_gart_disable(struct radeon_device *rdev)
{ {
u32 tmp; u32 tmp;
int r;
WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0); WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0); WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
...@@ -163,14 +162,7 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev) ...@@ -163,14 +162,7 @@ void rv370_pcie_gart_disable(struct radeon_device *rdev)
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void rv370_pcie_gart_fini(struct radeon_device *rdev) void rv370_pcie_gart_fini(struct radeon_device *rdev)
......
...@@ -763,13 +763,14 @@ void r600_hpd_init(struct radeon_device *rdev) ...@@ -763,13 +763,14 @@ void r600_hpd_init(struct radeon_device *rdev)
struct drm_device *dev = rdev->ddev; struct drm_device *dev = rdev->ddev;
struct drm_connector *connector; struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
if (ASIC_IS_DCE3(rdev)) { if (ASIC_IS_DCE3(rdev)) {
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
if (ASIC_IS_DCE32(rdev)) if (ASIC_IS_DCE32(rdev))
tmp |= DC_HPDx_EN; tmp |= DC_HPDx_EN;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
switch (radeon_connector->hpd.hpd) { switch (radeon_connector->hpd.hpd) {
case RADEON_HPD_1: case RADEON_HPD_1:
WREG32(DC_HPD1_CONTROL, tmp); WREG32(DC_HPD1_CONTROL, tmp);
...@@ -799,10 +800,7 @@ void r600_hpd_init(struct radeon_device *rdev) ...@@ -799,10 +800,7 @@ void r600_hpd_init(struct radeon_device *rdev)
default: default:
break; break;
} }
}
} else { } else {
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
switch (radeon_connector->hpd.hpd) { switch (radeon_connector->hpd.hpd) {
case RADEON_HPD_1: case RADEON_HPD_1:
WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN);
...@@ -820,6 +818,7 @@ void r600_hpd_init(struct radeon_device *rdev) ...@@ -820,6 +818,7 @@ void r600_hpd_init(struct radeon_device *rdev)
break; break;
} }
} }
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
} }
if (rdev->irq.installed) if (rdev->irq.installed)
r600_irq_set(rdev); r600_irq_set(rdev);
...@@ -897,7 +896,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev) ...@@ -897,7 +896,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev)
/* flush hdp cache so updates hit vram */ /* flush hdp cache so updates hit vram */
if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) &&
!(rdev->flags & RADEON_IS_AGP)) { !(rdev->flags & RADEON_IS_AGP)) {
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; void __iomem *ptr = (void *)rdev->gart.ptr;
u32 tmp; u32 tmp;
/* r7xx hw bug. write to HDP_DEBUG1 followed by fb read /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read
...@@ -932,7 +931,7 @@ int r600_pcie_gart_init(struct radeon_device *rdev) ...@@ -932,7 +931,7 @@ int r600_pcie_gart_init(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj) { if (rdev->gart.robj) {
WARN(1, "R600 PCIE GART already initialized\n"); WARN(1, "R600 PCIE GART already initialized\n");
return 0; return 0;
} }
...@@ -949,7 +948,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev) ...@@ -949,7 +948,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
u32 tmp; u32 tmp;
int r, i; int r, i;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -1004,7 +1003,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev) ...@@ -1004,7 +1003,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
void r600_pcie_gart_disable(struct radeon_device *rdev) void r600_pcie_gart_disable(struct radeon_device *rdev)
{ {
u32 tmp; u32 tmp;
int i, r; int i;
/* Disable all tables */ /* Disable all tables */
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
...@@ -1031,14 +1030,7 @@ void r600_pcie_gart_disable(struct radeon_device *rdev) ...@@ -1031,14 +1030,7 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp);
WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void r600_pcie_gart_fini(struct radeon_device *rdev) void r600_pcie_gart_fini(struct radeon_device *rdev)
...@@ -1138,7 +1130,7 @@ static void r600_mc_program(struct radeon_device *rdev) ...@@ -1138,7 +1130,7 @@ static void r600_mc_program(struct radeon_device *rdev)
WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12); WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12);
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12); WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12);
} }
WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
WREG32(MC_VM_FB_LOCATION, tmp); WREG32(MC_VM_FB_LOCATION, tmp);
...@@ -1277,6 +1269,53 @@ int r600_mc_init(struct radeon_device *rdev) ...@@ -1277,6 +1269,53 @@ int r600_mc_init(struct radeon_device *rdev)
return 0; return 0;
} }
int r600_vram_scratch_init(struct radeon_device *rdev)
{
int r;
if (rdev->vram_scratch.robj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
&rdev->vram_scratch.robj);
if (r) {
return r;
}
}
r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->vram_scratch.robj,
RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->vram_scratch.robj);
return r;
}
r = radeon_bo_kmap(rdev->vram_scratch.robj,
(void **)&rdev->vram_scratch.ptr);
if (r)
radeon_bo_unpin(rdev->vram_scratch.robj);
radeon_bo_unreserve(rdev->vram_scratch.robj);
return r;
}
void r600_vram_scratch_fini(struct radeon_device *rdev)
{
int r;
if (rdev->vram_scratch.robj == NULL) {
return;
}
r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->vram_scratch.robj);
radeon_bo_unpin(rdev->vram_scratch.robj);
radeon_bo_unreserve(rdev->vram_scratch.robj);
}
radeon_bo_unref(&rdev->vram_scratch.robj);
}
/* We doesn't check that the GPU really needs a reset we simply do the /* We doesn't check that the GPU really needs a reset we simply do the
* reset, it's up to the caller to determine if the GPU needs one. We * reset, it's up to the caller to determine if the GPU needs one. We
* might add an helper function to check that. * might add an helper function to check that.
...@@ -2332,6 +2371,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev, ...@@ -2332,6 +2371,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
if (rdev->wb.use_event) { if (rdev->wb.use_event) {
u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET + u64 addr = rdev->wb.gpu_addr + R600_WB_EVENT_OFFSET +
(u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base); (u64)(rdev->fence_drv.scratch_reg - rdev->scratch.reg_base);
/* flush read cache over gart */
radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
PACKET3_VC_ACTION_ENA |
PACKET3_SH_ACTION_ENA);
radeon_ring_write(rdev, 0xFFFFFFFF);
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, 10); /* poll interval */
/* EVENT_WRITE_EOP - flush caches, send int */ /* EVENT_WRITE_EOP - flush caches, send int */
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5));
...@@ -2340,6 +2387,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev, ...@@ -2340,6 +2387,14 @@ void r600_fence_ring_emit(struct radeon_device *rdev,
radeon_ring_write(rdev, fence->seq); radeon_ring_write(rdev, fence->seq);
radeon_ring_write(rdev, 0); radeon_ring_write(rdev, 0);
} else { } else {
/* flush read cache over gart */
radeon_ring_write(rdev, PACKET3(PACKET3_SURFACE_SYNC, 3));
radeon_ring_write(rdev, PACKET3_TC_ACTION_ENA |
PACKET3_VC_ACTION_ENA |
PACKET3_SH_ACTION_ENA);
radeon_ring_write(rdev, 0xFFFFFFFF);
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, 10); /* poll interval */
radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0)); radeon_ring_write(rdev, PACKET3(PACKET3_EVENT_WRITE, 0));
radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); radeon_ring_write(rdev, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0));
/* wait for 3D idle clean */ /* wait for 3D idle clean */
...@@ -2421,6 +2476,10 @@ int r600_startup(struct radeon_device *rdev) ...@@ -2421,6 +2476,10 @@ int r600_startup(struct radeon_device *rdev)
} }
} }
r = r600_vram_scratch_init(rdev);
if (r)
return r;
r600_mc_program(rdev); r600_mc_program(rdev);
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
r600_agp_enable(rdev); r600_agp_enable(rdev);
...@@ -2641,6 +2700,7 @@ void r600_fini(struct radeon_device *rdev) ...@@ -2641,6 +2700,7 @@ void r600_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
r600_pcie_gart_fini(rdev); r600_pcie_gart_fini(rdev);
r600_vram_scratch_fini(rdev);
radeon_agp_fini(rdev); radeon_agp_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
......
...@@ -201,7 +201,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr) ...@@ -201,7 +201,7 @@ set_vtx_resource(struct radeon_device *rdev, u64 gpu_addr)
static void static void
set_tex_resource(struct radeon_device *rdev, set_tex_resource(struct radeon_device *rdev,
int format, int w, int h, int pitch, int format, int w, int h, int pitch,
u64 gpu_addr) u64 gpu_addr, u32 size)
{ {
uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4; uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4;
...@@ -222,6 +222,9 @@ set_tex_resource(struct radeon_device *rdev, ...@@ -222,6 +222,9 @@ set_tex_resource(struct radeon_device *rdev,
S_038010_DST_SEL_Z(SQ_SEL_Z) | S_038010_DST_SEL_Z(SQ_SEL_Z) |
S_038010_DST_SEL_W(SQ_SEL_W); S_038010_DST_SEL_W(SQ_SEL_W);
cp_set_surface_sync(rdev,
PACKET3_TC_ACTION_ENA, size, gpu_addr);
radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7)); radeon_ring_write(rdev, PACKET3(PACKET3_SET_RESOURCE, 7));
radeon_ring_write(rdev, 0); radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, sq_tex_resource_word0); radeon_ring_write(rdev, sq_tex_resource_word0);
...@@ -500,9 +503,9 @@ int r600_blit_init(struct radeon_device *rdev) ...@@ -500,9 +503,9 @@ int r600_blit_init(struct radeon_device *rdev)
rdev->r600_blit.primitives.set_default_state = set_default_state; rdev->r600_blit.primitives.set_default_state = set_default_state;
rdev->r600_blit.ring_size_common = 40; /* shaders + def state */ rdev->r600_blit.ring_size_common = 40; /* shaders + def state */
rdev->r600_blit.ring_size_common += 10; /* fence emit for VB IB */ rdev->r600_blit.ring_size_common += 16; /* fence emit for VB IB */
rdev->r600_blit.ring_size_common += 5; /* done copy */ rdev->r600_blit.ring_size_common += 5; /* done copy */
rdev->r600_blit.ring_size_common += 10; /* fence emit for done copy */ rdev->r600_blit.ring_size_common += 16; /* fence emit for done copy */
rdev->r600_blit.ring_size_per_loop = 76; rdev->r600_blit.ring_size_per_loop = 76;
/* set_render_target emits 2 extra dwords on rv6xx */ /* set_render_target emits 2 extra dwords on rv6xx */
...@@ -760,10 +763,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, ...@@ -760,10 +763,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,
vb[11] = i2f(h); vb[11] = i2f(h);
rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8, rdev->r600_blit.primitives.set_tex_resource(rdev, FMT_8_8_8_8,
w, h, w, src_gpu_addr); w, h, w, src_gpu_addr, size_in_bytes);
rdev->r600_blit.primitives.cp_set_surface_sync(rdev,
PACKET3_TC_ACTION_ENA,
size_in_bytes, src_gpu_addr);
rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8, rdev->r600_blit.primitives.set_render_target(rdev, COLOR_8_8_8_8,
w, h, dst_gpu_addr); w, h, dst_gpu_addr);
rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h); rdev->r600_blit.primitives.set_scissors(rdev, 0, 0, w, h);
......
...@@ -93,6 +93,7 @@ extern int radeon_audio; ...@@ -93,6 +93,7 @@ extern int radeon_audio;
extern int radeon_disp_priority; extern int radeon_disp_priority;
extern int radeon_hw_i2c; extern int radeon_hw_i2c;
extern int radeon_pcie_gen2; extern int radeon_pcie_gen2;
extern int radeon_msi;
/* /*
* Copy from radeon_drv.h so we don't have to include both and have conflicting * Copy from radeon_drv.h so we don't have to include both and have conflicting
...@@ -306,30 +307,17 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv, ...@@ -306,30 +307,17 @@ int radeon_mode_dumb_destroy(struct drm_file *file_priv,
*/ */
struct radeon_mc; struct radeon_mc;
struct radeon_gart_table_ram {
volatile uint32_t *ptr;
};
struct radeon_gart_table_vram {
struct radeon_bo *robj;
volatile uint32_t *ptr;
};
union radeon_gart_table {
struct radeon_gart_table_ram ram;
struct radeon_gart_table_vram vram;
};
#define RADEON_GPU_PAGE_SIZE 4096 #define RADEON_GPU_PAGE_SIZE 4096
#define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1) #define RADEON_GPU_PAGE_MASK (RADEON_GPU_PAGE_SIZE - 1)
#define RADEON_GPU_PAGE_SHIFT 12 #define RADEON_GPU_PAGE_SHIFT 12
struct radeon_gart { struct radeon_gart {
dma_addr_t table_addr; dma_addr_t table_addr;
struct radeon_bo *robj;
void *ptr;
unsigned num_gpu_pages; unsigned num_gpu_pages;
unsigned num_cpu_pages; unsigned num_cpu_pages;
unsigned table_size; unsigned table_size;
union radeon_gart_table table;
struct page **pages; struct page **pages;
dma_addr_t *pages_addr; dma_addr_t *pages_addr;
bool *ttm_alloced; bool *ttm_alloced;
...@@ -340,6 +328,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev); ...@@ -340,6 +328,8 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev);
void radeon_gart_table_ram_free(struct radeon_device *rdev); void radeon_gart_table_ram_free(struct radeon_device *rdev);
int radeon_gart_table_vram_alloc(struct radeon_device *rdev); int radeon_gart_table_vram_alloc(struct radeon_device *rdev);
void radeon_gart_table_vram_free(struct radeon_device *rdev); void radeon_gart_table_vram_free(struct radeon_device *rdev);
int radeon_gart_table_vram_pin(struct radeon_device *rdev);
void radeon_gart_table_vram_unpin(struct radeon_device *rdev);
int radeon_gart_init(struct radeon_device *rdev); int radeon_gart_init(struct radeon_device *rdev);
void radeon_gart_fini(struct radeon_device *rdev); void radeon_gart_fini(struct radeon_device *rdev);
void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
...@@ -347,6 +337,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, ...@@ -347,6 +337,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, struct page **pagelist, int pages, struct page **pagelist,
dma_addr_t *dma_addr); dma_addr_t *dma_addr);
void radeon_gart_restore(struct radeon_device *rdev);
/* /*
...@@ -437,25 +428,26 @@ union radeon_irq_stat_regs { ...@@ -437,25 +428,26 @@ union radeon_irq_stat_regs {
struct evergreen_irq_stat_regs evergreen; struct evergreen_irq_stat_regs evergreen;
}; };
#define RADEON_MAX_HPD_PINS 6
#define RADEON_MAX_CRTCS 6
#define RADEON_MAX_HDMI_BLOCKS 2
struct radeon_irq { struct radeon_irq {
bool installed; bool installed;
bool sw_int; bool sw_int;
/* FIXME: use a define max crtc rather than hardcode it */ bool crtc_vblank_int[RADEON_MAX_CRTCS];
bool crtc_vblank_int[6]; bool pflip[RADEON_MAX_CRTCS];
bool pflip[6];
wait_queue_head_t vblank_queue; wait_queue_head_t vblank_queue;
/* FIXME: use defines for max hpd/dacs */ bool hpd[RADEON_MAX_HPD_PINS];
bool hpd[6];
bool gui_idle; bool gui_idle;
bool gui_idle_acked; bool gui_idle_acked;
wait_queue_head_t idle_queue; wait_queue_head_t idle_queue;
/* FIXME: use defines for max HDMI blocks */ bool hdmi[RADEON_MAX_HDMI_BLOCKS];
bool hdmi[2];
spinlock_t sw_lock; spinlock_t sw_lock;
int sw_refcount; int sw_refcount;
union radeon_irq_stat_regs stat_regs; union radeon_irq_stat_regs stat_regs;
spinlock_t pflip_lock[6]; spinlock_t pflip_lock[RADEON_MAX_CRTCS];
int pflip_refcount[6]; int pflip_refcount[RADEON_MAX_CRTCS];
}; };
int radeon_irq_kms_init(struct radeon_device *rdev); int radeon_irq_kms_init(struct radeon_device *rdev);
...@@ -533,7 +525,7 @@ struct r600_blit_cp_primitives { ...@@ -533,7 +525,7 @@ struct r600_blit_cp_primitives {
void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr); void (*set_vtx_resource)(struct radeon_device *rdev, u64 gpu_addr);
void (*set_tex_resource)(struct radeon_device *rdev, void (*set_tex_resource)(struct radeon_device *rdev,
int format, int w, int h, int pitch, int format, int w, int h, int pitch,
u64 gpu_addr); u64 gpu_addr, u32 size);
void (*set_scissors)(struct radeon_device *rdev, int x1, int y1, void (*set_scissors)(struct radeon_device *rdev, int x1, int y1,
int x2, int y2); int x2, int y2);
void (*draw_auto)(struct radeon_device *rdev); void (*draw_auto)(struct radeon_device *rdev);
...@@ -1143,10 +1135,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data, ...@@ -1143,10 +1135,11 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data, int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp); struct drm_file *filp);
/* VRAM scratch page for HDP bug */ /* VRAM scratch page for HDP bug, default vram page */
struct r700_vram_scratch { struct r600_vram_scratch {
struct radeon_bo *robj; struct radeon_bo *robj;
volatile uint32_t *ptr; volatile uint32_t *ptr;
u64 gpu_addr;
}; };
/* /*
...@@ -1218,7 +1211,7 @@ struct radeon_device { ...@@ -1218,7 +1211,7 @@ struct radeon_device {
const struct firmware *rlc_fw; /* r6/700 RLC firmware */ const struct firmware *rlc_fw; /* r6/700 RLC firmware */
const struct firmware *mc_fw; /* NI MC firmware */ const struct firmware *mc_fw; /* NI MC firmware */
struct r600_blit r600_blit; struct r600_blit r600_blit;
struct r700_vram_scratch vram_scratch; struct r600_vram_scratch vram_scratch;
int msi_enabled; /* msi enabled */ int msi_enabled; /* msi enabled */
struct r600_ih ih; /* r6/700 interrupt ring */ struct r600_ih ih; /* r6/700 interrupt ring */
struct work_struct hotplug_work; struct work_struct hotplug_work;
...@@ -1442,8 +1435,6 @@ void radeon_ring_write(struct radeon_device *rdev, uint32_t v); ...@@ -1442,8 +1435,6 @@ void radeon_ring_write(struct radeon_device *rdev, uint32_t v);
/* AGP */ /* AGP */
extern int radeon_gpu_reset(struct radeon_device *rdev); extern int radeon_gpu_reset(struct radeon_device *rdev);
extern void radeon_agp_disable(struct radeon_device *rdev); extern void radeon_agp_disable(struct radeon_device *rdev);
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
extern void radeon_gart_restore(struct radeon_device *rdev);
extern int radeon_modeset_init(struct radeon_device *rdev); extern int radeon_modeset_init(struct radeon_device *rdev);
extern void radeon_modeset_fini(struct radeon_device *rdev); extern void radeon_modeset_fini(struct radeon_device *rdev);
extern bool radeon_card_posted(struct radeon_device *rdev); extern bool radeon_card_posted(struct radeon_device *rdev);
...@@ -1466,6 +1457,12 @@ extern int radeon_resume_kms(struct drm_device *dev); ...@@ -1466,6 +1457,12 @@ extern int radeon_resume_kms(struct drm_device *dev);
extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size); extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
/*
* R600 vram scratch functions
*/
int r600_vram_scratch_init(struct radeon_device *rdev);
void r600_vram_scratch_fini(struct radeon_device *rdev);
/* /*
* r600 functions used by radeon_encoder.c * r600 functions used by radeon_encoder.c
*/ */
......
...@@ -44,8 +44,6 @@ extern void ...@@ -44,8 +44,6 @@ extern void
radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder, radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
struct drm_connector *drm_connector); struct drm_connector *drm_connector);
bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
void radeon_connector_hotplug(struct drm_connector *connector) void radeon_connector_hotplug(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
...@@ -432,55 +430,6 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr ...@@ -432,55 +430,6 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
return 0; return 0;
} }
/*
* Some integrated ATI Radeon chipset implementations (e. g.
* Asus M2A-VM HDMI) may indicate the availability of a DDC,
* even when there's no monitor connected. For these connectors
* following DDC probe extension will be applied: check also for the
* availability of EDID with at least a correct EDID header. Only then,
* DDC is assumed to be available. This prevents drm_get_edid() and
* drm_edid_block_valid() from periodically dumping data and kernel
* errors into the logs and onto the terminal.
*/
static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
uint32_t supported_device,
int connector_type)
{
/* Asus M2A-VM HDMI board sends data to i2c bus even,
* if HDMI add-on card is not plugged in or HDMI is disabled in
* BIOS. Valid DDC can only be assumed, if also a valid EDID header
* can be retrieved via i2c bus during DDC probe */
if ((dev->pdev->device == 0x791e) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
(dev->pdev->subsystem_device == 0x826d)) {
if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}
/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
* for a DVI connector that is not implemented */
if ((dev->pdev->device == 0x796e) &&
(dev->pdev->subsystem_vendor == 0x1019) &&
(dev->pdev->subsystem_device == 0x2615)) {
if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}
/* TOSHIBA Satellite L300D with ATI Mobility Radeon x1100
* (RS690M) sends data to i2c bus for a HDMI connector that
* is not implemented */
if ((dev->pdev->device == 0x791f) &&
(dev->pdev->subsystem_vendor == 0x1179) &&
(dev->pdev->subsystem_device == 0xff68)) {
if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
(supported_device == ATOM_DEVICE_DFP2_SUPPORT))
return true;
}
/* Default: no EDID header probe required for DDC probing */
return false;
}
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder, static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
struct drm_connector *connector) struct drm_connector *connector)
{ {
...@@ -721,8 +670,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) ...@@ -721,8 +670,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
ret = connector_status_disconnected; ret = connector_status_disconnected;
if (radeon_connector->ddc_bus) if (radeon_connector->ddc_bus)
dret = radeon_ddc_probe(radeon_connector, dret = radeon_ddc_probe(radeon_connector);
radeon_connector->requires_extended_probe);
if (dret) { if (dret) {
radeon_connector->detected_by_load = false; radeon_connector->detected_by_load = false;
if (radeon_connector->edid) { if (radeon_connector->edid) {
...@@ -764,7 +712,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) ...@@ -764,7 +712,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
if (radeon_connector->dac_load_detect && encoder) { if (radeon_connector->dac_load_detect && encoder) {
encoder_funcs = encoder->helper_private; encoder_funcs = encoder->helper_private;
ret = encoder_funcs->detect(encoder, connector); ret = encoder_funcs->detect(encoder, connector);
if (ret == connector_status_connected) if (ret != connector_status_disconnected)
radeon_connector->detected_by_load = true; radeon_connector->detected_by_load = true;
} }
} }
...@@ -904,8 +852,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ...@@ -904,8 +852,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
bool dret = false; bool dret = false;
if (radeon_connector->ddc_bus) if (radeon_connector->ddc_bus)
dret = radeon_ddc_probe(radeon_connector, dret = radeon_ddc_probe(radeon_connector);
radeon_connector->requires_extended_probe);
if (dret) { if (dret) {
radeon_connector->detected_by_load = false; radeon_connector->detected_by_load = false;
if (radeon_connector->edid) { if (radeon_connector->edid) {
...@@ -1005,8 +952,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ...@@ -1005,8 +952,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
ret = encoder_funcs->detect(encoder, connector); ret = encoder_funcs->detect(encoder, connector);
if (ret == connector_status_connected) { if (ret == connector_status_connected) {
radeon_connector->use_digital = false; radeon_connector->use_digital = false;
radeon_connector->detected_by_load = true;
} }
if (ret != connector_status_disconnected)
radeon_connector->detected_by_load = true;
} }
break; break;
} }
...@@ -1203,7 +1151,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) ...@@ -1203,7 +1151,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
} }
} else { } else {
/* need to setup ddc on the bridge */ /* need to setup ddc on the bridge */
if (radeon_connector_encoder_is_dp_bridge(connector)) { if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
ENCODER_OBJECT_ID_NONE) {
if (encoder) if (encoder)
radeon_atom_ext_encoder_setup_ddc(encoder); radeon_atom_ext_encoder_setup_ddc(encoder);
} }
...@@ -1213,13 +1162,12 @@ static int radeon_dp_get_modes(struct drm_connector *connector) ...@@ -1213,13 +1162,12 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
return ret; return ret;
} }
bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector) u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector)
{ {
struct drm_mode_object *obj; struct drm_mode_object *obj;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder; struct radeon_encoder *radeon_encoder;
int i; int i;
bool found = false;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0) if (connector->encoder_ids[i] == 0)
...@@ -1235,14 +1183,13 @@ bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector) ...@@ -1235,14 +1183,13 @@ bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector)
switch (radeon_encoder->encoder_id) { switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_TRAVIS: case ENCODER_OBJECT_ID_TRAVIS:
case ENCODER_OBJECT_ID_NUTMEG: case ENCODER_OBJECT_ID_NUTMEG:
found = true; return radeon_encoder->encoder_id;
break;
default: default:
break; break;
} }
} }
return found; return ENCODER_OBJECT_ID_NONE;
} }
bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector) bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
...@@ -1319,7 +1266,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ...@@ -1319,7 +1266,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
if (!radeon_dig_connector->edp_on) if (!radeon_dig_connector->edp_on)
atombios_set_edp_panel_power(connector, atombios_set_edp_panel_power(connector,
ATOM_TRANSMITTER_ACTION_POWER_OFF); ATOM_TRANSMITTER_ACTION_POWER_OFF);
} else if (radeon_connector_encoder_is_dp_bridge(connector)) { } else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) !=
ENCODER_OBJECT_ID_NONE) {
/* DP bridges are always DP */ /* DP bridges are always DP */
radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT; radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
/* get the DPCD from the bridge */ /* get the DPCD from the bridge */
...@@ -1328,8 +1276,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ...@@ -1328,8 +1276,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
if (encoder) { if (encoder) {
/* setup ddc on the bridge */ /* setup ddc on the bridge */
radeon_atom_ext_encoder_setup_ddc(encoder); radeon_atom_ext_encoder_setup_ddc(encoder);
if (radeon_ddc_probe(radeon_connector, if (radeon_ddc_probe(radeon_connector)) /* try DDC */
radeon_connector->requires_extended_probe)) /* try DDC */
ret = connector_status_connected; ret = connector_status_connected;
else if (radeon_connector->dac_load_detect) { /* try load detection */ else if (radeon_connector->dac_load_detect) { /* try load detection */
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
...@@ -1347,8 +1294,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) ...@@ -1347,8 +1294,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
if (radeon_dp_getdpcd(radeon_connector)) if (radeon_dp_getdpcd(radeon_connector))
ret = connector_status_connected; ret = connector_status_connected;
} else { } else {
if (radeon_ddc_probe(radeon_connector, if (radeon_ddc_probe(radeon_connector))
radeon_connector->requires_extended_probe))
ret = connector_status_connected; ret = connector_status_connected;
} }
} }
...@@ -1493,9 +1439,7 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1493,9 +1439,7 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_connector->shared_ddc = shared_ddc; radeon_connector->shared_ddc = shared_ddc;
radeon_connector->connector_object_id = connector_object_id; radeon_connector->connector_object_id = connector_object_id;
radeon_connector->hpd = *hpd; radeon_connector->hpd = *hpd;
radeon_connector->requires_extended_probe =
radeon_connector_needs_extended_probe(rdev, supported_device,
connector_type);
radeon_connector->router = *router; radeon_connector->router = *router;
if (router->ddc_valid || router->cd_valid) { if (router->ddc_valid || router->cd_valid) {
radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info); radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
...@@ -1842,9 +1786,7 @@ radeon_add_legacy_connector(struct drm_device *dev, ...@@ -1842,9 +1786,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
radeon_connector->devices = supported_device; radeon_connector->devices = supported_device;
radeon_connector->connector_object_id = connector_object_id; radeon_connector->connector_object_id = connector_object_id;
radeon_connector->hpd = *hpd; radeon_connector->hpd = *hpd;
radeon_connector->requires_extended_probe =
radeon_connector_needs_extended_probe(rdev, supported_device,
connector_type);
switch (connector_type) { switch (connector_type) {
case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_VGA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
......
...@@ -33,8 +33,6 @@ ...@@ -33,8 +33,6 @@
#include "drm_crtc_helper.h" #include "drm_crtc_helper.h"
#include "drm_edid.h" #include "drm_edid.h"
static int radeon_ddc_dump(struct drm_connector *connector);
static void avivo_crtc_load_lut(struct drm_crtc *crtc) static void avivo_crtc_load_lut(struct drm_crtc *crtc)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
...@@ -669,7 +667,6 @@ static void radeon_print_display_setup(struct drm_device *dev) ...@@ -669,7 +667,6 @@ static void radeon_print_display_setup(struct drm_device *dev)
static bool radeon_setup_enc_conn(struct drm_device *dev) static bool radeon_setup_enc_conn(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct drm_connector *drm_connector;
bool ret = false; bool ret = false;
if (rdev->bios) { if (rdev->bios) {
...@@ -689,8 +686,6 @@ static bool radeon_setup_enc_conn(struct drm_device *dev) ...@@ -689,8 +686,6 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
if (ret) { if (ret) {
radeon_setup_encoder_clones(dev); radeon_setup_encoder_clones(dev);
radeon_print_display_setup(dev); radeon_print_display_setup(dev);
list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
radeon_ddc_dump(drm_connector);
} }
return ret; return ret;
...@@ -708,7 +703,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) ...@@ -708,7 +703,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) ||
(radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) ||
radeon_connector_encoder_is_dp_bridge(&radeon_connector->base)) { (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) !=
ENCODER_OBJECT_ID_NONE)) {
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT ||
...@@ -743,34 +739,6 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) ...@@ -743,34 +739,6 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
return 0; return 0;
} }
static int radeon_ddc_dump(struct drm_connector *connector)
{
struct edid *edid;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int ret = 0;
/* on hw with routers, select right port */
if (radeon_connector->router.ddc_valid)
radeon_router_select_ddc_port(radeon_connector);
if (!radeon_connector->ddc_bus)
return -1;
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
/* Log EDID retrieval status here. In particular with regard to
* connectors with requires_extended_probe flag set, that will prevent
* function radeon_dvi_detect() to fetch EDID on this connector,
* as long as there is no valid EDID header found */
if (edid) {
DRM_INFO("Radeon display connector %s: Found valid EDID",
drm_get_connector_name(connector));
kfree(edid);
} else {
DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
drm_get_connector_name(connector));
}
return ret;
}
/* avivo */ /* avivo */
static void avivo_get_fb_div(struct radeon_pll *pll, static void avivo_get_fb_div(struct radeon_pll *pll,
u32 target_clock, u32 target_clock,
......
...@@ -119,6 +119,7 @@ int radeon_audio = 0; ...@@ -119,6 +119,7 @@ int radeon_audio = 0;
int radeon_disp_priority = 0; int radeon_disp_priority = 0;
int radeon_hw_i2c = 0; int radeon_hw_i2c = 0;
int radeon_pcie_gen2 = 0; int radeon_pcie_gen2 = 0;
int radeon_msi = -1;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444); module_param_named(no_wb, radeon_no_wb, int, 0444);
...@@ -165,6 +166,9 @@ module_param_named(hw_i2c, radeon_hw_i2c, int, 0444); ...@@ -165,6 +166,9 @@ module_param_named(hw_i2c, radeon_hw_i2c, int, 0444);
MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)"); MODULE_PARM_DESC(pcie_gen2, "PCIE Gen2 mode (1 = enable)");
module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444); module_param_named(pcie_gen2, radeon_pcie_gen2, int, 0444);
MODULE_PARM_DESC(msi, "MSI support (1 = enable, 0 = disable, -1 = auto)");
module_param_named(msi, radeon_msi, int, 0444);
static int radeon_suspend(struct drm_device *dev, pm_message_t state) static int radeon_suspend(struct drm_device *dev, pm_message_t state)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
......
This diff is collapsed.
...@@ -49,27 +49,27 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev) ...@@ -49,27 +49,27 @@ int radeon_gart_table_ram_alloc(struct radeon_device *rdev)
rdev->gart.table_size >> PAGE_SHIFT); rdev->gart.table_size >> PAGE_SHIFT);
} }
#endif #endif
rdev->gart.table.ram.ptr = ptr; rdev->gart.ptr = ptr;
memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size); memset((void *)rdev->gart.ptr, 0, rdev->gart.table_size);
return 0; return 0;
} }
void radeon_gart_table_ram_free(struct radeon_device *rdev) void radeon_gart_table_ram_free(struct radeon_device *rdev)
{ {
if (rdev->gart.table.ram.ptr == NULL) { if (rdev->gart.ptr == NULL) {
return; return;
} }
#ifdef CONFIG_X86 #ifdef CONFIG_X86
if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 ||
rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
set_memory_wb((unsigned long)rdev->gart.table.ram.ptr, set_memory_wb((unsigned long)rdev->gart.ptr,
rdev->gart.table_size >> PAGE_SHIFT); rdev->gart.table_size >> PAGE_SHIFT);
} }
#endif #endif
pci_free_consistent(rdev->pdev, rdev->gart.table_size, pci_free_consistent(rdev->pdev, rdev->gart.table_size,
(void *)rdev->gart.table.ram.ptr, (void *)rdev->gart.ptr,
rdev->gart.table_addr); rdev->gart.table_addr);
rdev->gart.table.ram.ptr = NULL; rdev->gart.ptr = NULL;
rdev->gart.table_addr = 0; rdev->gart.table_addr = 0;
} }
...@@ -77,10 +77,10 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev) ...@@ -77,10 +77,10 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
r = radeon_bo_create(rdev, rdev->gart.table_size, r = radeon_bo_create(rdev, rdev->gart.table_size,
PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
&rdev->gart.table.vram.robj); &rdev->gart.robj);
if (r) { if (r) {
return r; return r;
} }
...@@ -93,38 +93,46 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) ...@@ -93,38 +93,46 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev)
uint64_t gpu_addr; uint64_t gpu_addr;
int r; int r;
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); r = radeon_bo_reserve(rdev->gart.robj, false);
if (unlikely(r != 0)) if (unlikely(r != 0))
return r; return r;
r = radeon_bo_pin(rdev->gart.table.vram.robj, r = radeon_bo_pin(rdev->gart.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr); RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) { if (r) {
radeon_bo_unreserve(rdev->gart.table.vram.robj); radeon_bo_unreserve(rdev->gart.robj);
return r; return r;
} }
r = radeon_bo_kmap(rdev->gart.table.vram.robj, r = radeon_bo_kmap(rdev->gart.robj, &rdev->gart.ptr);
(void **)&rdev->gart.table.vram.ptr);
if (r) if (r)
radeon_bo_unpin(rdev->gart.table.vram.robj); radeon_bo_unpin(rdev->gart.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj); radeon_bo_unreserve(rdev->gart.robj);
rdev->gart.table_addr = gpu_addr; rdev->gart.table_addr = gpu_addr;
return r; return r;
} }
void radeon_gart_table_vram_free(struct radeon_device *rdev) void radeon_gart_table_vram_unpin(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
return; return;
} }
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); r = radeon_bo_reserve(rdev->gart.robj, false);
if (likely(r == 0)) { if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj); radeon_bo_kunmap(rdev->gart.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj); radeon_bo_unpin(rdev->gart.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj); radeon_bo_unreserve(rdev->gart.robj);
rdev->gart.ptr = NULL;
} }
radeon_bo_unref(&rdev->gart.table.vram.robj); }
void radeon_gart_table_vram_free(struct radeon_device *rdev)
{
if (rdev->gart.robj == NULL) {
return;
}
radeon_gart_table_vram_unpin(rdev);
radeon_bo_unref(&rdev->gart.robj);
} }
...@@ -156,7 +164,9 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, ...@@ -156,7 +164,9 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
rdev->gart.pages_addr[p] = rdev->dummy_page.addr; rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
page_base = rdev->gart.pages_addr[p]; page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
if (rdev->gart.ptr) {
radeon_gart_set_page(rdev, t, page_base); radeon_gart_set_page(rdev, t, page_base);
}
page_base += RADEON_GPU_PAGE_SIZE; page_base += RADEON_GPU_PAGE_SIZE;
} }
} }
...@@ -199,12 +209,14 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, ...@@ -199,12 +209,14 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
} }
} }
rdev->gart.pages[p] = pagelist[i]; rdev->gart.pages[p] = pagelist[i];
if (rdev->gart.ptr) {
page_base = rdev->gart.pages_addr[p]; page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
radeon_gart_set_page(rdev, t, page_base); radeon_gart_set_page(rdev, t, page_base);
page_base += RADEON_GPU_PAGE_SIZE; page_base += RADEON_GPU_PAGE_SIZE;
} }
} }
}
mb(); mb();
radeon_gart_tlb_flush(rdev); radeon_gart_tlb_flush(rdev);
return 0; return 0;
...@@ -215,6 +227,9 @@ void radeon_gart_restore(struct radeon_device *rdev) ...@@ -215,6 +227,9 @@ void radeon_gart_restore(struct radeon_device *rdev)
int i, j, t; int i, j, t;
u64 page_base; u64 page_base;
if (!rdev->gart.ptr) {
return;
}
for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) { for (i = 0, t = 0; i < rdev->gart.num_cpu_pages; i++) {
page_base = rdev->gart.pages_addr[i]; page_base = rdev->gart.pages_addr[i];
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* radeon_ddc_probe * radeon_ddc_probe
* *
*/ */
bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe) bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
{ {
u8 out = 0x0; u8 out = 0x0;
u8 buf[8]; u8 buf[8];
...@@ -49,15 +49,11 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e ...@@ -49,15 +49,11 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
{ {
.addr = 0x50, .addr = 0x50,
.flags = I2C_M_RD, .flags = I2C_M_RD,
.len = 1, .len = 8,
.buf = buf, .buf = buf,
} }
}; };
/* Read 8 bytes from i2c for extended probe of EDID header */
if (requires_extended_probe)
msgs[1].len = 8;
/* on hw with routers, select right port */ /* on hw with routers, select right port */
if (radeon_connector->router.ddc_valid) if (radeon_connector->router.ddc_valid)
radeon_router_select_ddc_port(radeon_connector); radeon_router_select_ddc_port(radeon_connector);
...@@ -66,7 +62,6 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e ...@@ -66,7 +62,6 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
if (ret != 2) if (ret != 2)
/* Couldn't find an accessible DDC on this connector */ /* Couldn't find an accessible DDC on this connector */
return false; return false;
if (requires_extended_probe) {
/* Probe also for valid EDID header /* Probe also for valid EDID header
* EDID header starts with: * EDID header starts with:
* 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00. * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
...@@ -77,7 +72,6 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e ...@@ -77,7 +72,6 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_e
* connector */ * connector */
return false; return false;
} }
}
return true; return true;
} }
......
...@@ -67,10 +67,10 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) ...@@ -67,10 +67,10 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
/* Disable *all* interrupts */ /* Disable *all* interrupts */
rdev->irq.sw_int = false; rdev->irq.sw_int = false;
rdev->irq.gui_idle = false; rdev->irq.gui_idle = false;
for (i = 0; i < rdev->num_crtc; i++) for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
rdev->irq.crtc_vblank_int[i] = false;
for (i = 0; i < 6; i++) {
rdev->irq.hpd[i] = false; rdev->irq.hpd[i] = false;
for (i = 0; i < RADEON_MAX_CRTCS; i++) {
rdev->irq.crtc_vblank_int[i] = false;
rdev->irq.pflip[i] = false; rdev->irq.pflip[i] = false;
} }
radeon_irq_set(rdev); radeon_irq_set(rdev);
...@@ -99,15 +99,55 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) ...@@ -99,15 +99,55 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
/* Disable *all* interrupts */ /* Disable *all* interrupts */
rdev->irq.sw_int = false; rdev->irq.sw_int = false;
rdev->irq.gui_idle = false; rdev->irq.gui_idle = false;
for (i = 0; i < rdev->num_crtc; i++) for (i = 0; i < RADEON_MAX_HPD_PINS; i++)
rdev->irq.crtc_vblank_int[i] = false;
for (i = 0; i < 6; i++) {
rdev->irq.hpd[i] = false; rdev->irq.hpd[i] = false;
for (i = 0; i < RADEON_MAX_CRTCS; i++) {
rdev->irq.crtc_vblank_int[i] = false;
rdev->irq.pflip[i] = false; rdev->irq.pflip[i] = false;
} }
radeon_irq_set(rdev); radeon_irq_set(rdev);
} }
static bool radeon_msi_ok(struct radeon_device *rdev)
{
/* RV370/RV380 was first asic with MSI support */
if (rdev->family < CHIP_RV380)
return false;
/* MSIs don't work on AGP */
if (rdev->flags & RADEON_IS_AGP)
return false;
/* force MSI on */
if (radeon_msi == 1)
return true;
else if (radeon_msi == 0)
return false;
/* Quirks */
/* HP RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x103c) &&
(rdev->pdev->subsystem_device == 0x30c2))
return true;
/* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) &&
(rdev->pdev->subsystem_device == 0x01fd))
return true;
if (rdev->flags & RADEON_IS_IGP) {
/* APUs work fine with MSIs */
if (rdev->family >= CHIP_PALM)
return true;
/* lots of IGPs have problems with MSIs */
return false;
}
return true;
}
int radeon_irq_kms_init(struct radeon_device *rdev) int radeon_irq_kms_init(struct radeon_device *rdev)
{ {
int i; int i;
...@@ -124,12 +164,8 @@ int radeon_irq_kms_init(struct radeon_device *rdev) ...@@ -124,12 +164,8 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
} }
/* enable msi */ /* enable msi */
rdev->msi_enabled = 0; rdev->msi_enabled = 0;
/* MSIs don't seem to work reliably on all IGP
* chips. Disable MSI on them for now. if (radeon_msi_ok(rdev)) {
*/
if ((rdev->family >= CHIP_RV380) &&
((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) &&
(!(rdev->flags & RADEON_IS_AGP))) {
int ret = pci_enable_msi(rdev->pdev); int ret = pci_enable_msi(rdev->pdev);
if (!ret) { if (!ret) {
rdev->msi_enabled = 1; rdev->msi_enabled = 1;
......
...@@ -438,9 +438,6 @@ struct radeon_connector { ...@@ -438,9 +438,6 @@ struct radeon_connector {
struct radeon_i2c_chan *ddc_bus; struct radeon_i2c_chan *ddc_bus;
/* some systems have an hdmi and vga port with a shared ddc line */ /* some systems have an hdmi and vga port with a shared ddc line */
bool shared_ddc; bool shared_ddc;
/* for some Radeon chip families we apply an additional EDID header
check as part of the DDC probe */
bool requires_extended_probe;
bool use_digital; bool use_digital;
/* we need to mind the EDID between detect /* we need to mind the EDID between detect
and get modes due to analog/digital/tvencoder */ and get modes due to analog/digital/tvencoder */
...@@ -459,6 +456,8 @@ struct radeon_framebuffer { ...@@ -459,6 +456,8 @@ struct radeon_framebuffer {
struct drm_gem_object *obj; struct drm_gem_object *obj;
}; };
#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
((em) == ATOM_ENCODER_MODE_DP_MST))
extern enum radeon_tv_std extern enum radeon_tv_std
radeon_combios_get_tv_info(struct radeon_device *rdev); radeon_combios_get_tv_info(struct radeon_device *rdev);
...@@ -468,8 +467,8 @@ radeon_atombios_get_tv_info(struct radeon_device *rdev); ...@@ -468,8 +467,8 @@ 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 bool radeon_encoder_is_dp_bridge(struct drm_encoder *encoder); extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
extern bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector); extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector); extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector); extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
...@@ -489,7 +488,7 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, ...@@ -489,7 +488,7 @@ 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);
extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder); extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder);
extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
u8 write_byte, u8 *read_byte); u8 write_byte, u8 *read_byte);
...@@ -519,8 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, ...@@ -519,8 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
u8 val); u8 val);
extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
bool requires_extended_probe);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
......
...@@ -77,7 +77,7 @@ int rs400_gart_init(struct radeon_device *rdev) ...@@ -77,7 +77,7 @@ int rs400_gart_init(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.ram.ptr) { if (rdev->gart.ptr) {
WARN(1, "RS400 GART already initialized\n"); WARN(1, "RS400 GART already initialized\n");
return 0; return 0;
} }
...@@ -212,6 +212,7 @@ void rs400_gart_fini(struct radeon_device *rdev) ...@@ -212,6 +212,7 @@ void rs400_gart_fini(struct radeon_device *rdev)
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
uint32_t entry; uint32_t entry;
u32 *gtt = rdev->gart.ptr;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
...@@ -221,7 +222,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) ...@@ -221,7 +222,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
((upper_32_bits(addr) & 0xff) << 4) | ((upper_32_bits(addr) & 0xff) << 4) |
RS400_PTE_WRITEABLE | RS400_PTE_READABLE; RS400_PTE_WRITEABLE | RS400_PTE_READABLE;
entry = cpu_to_le32(entry); entry = cpu_to_le32(entry);
rdev->gart.table.ram.ptr[i] = entry; gtt[i] = entry;
return 0; return 0;
} }
......
...@@ -287,6 +287,7 @@ void rs600_hpd_init(struct radeon_device *rdev) ...@@ -287,6 +287,7 @@ void rs600_hpd_init(struct radeon_device *rdev)
default: default:
break; break;
} }
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
} }
if (rdev->irq.installed) if (rdev->irq.installed)
rs600_irq_set(rdev); rs600_irq_set(rdev);
...@@ -413,7 +414,7 @@ int rs600_gart_init(struct radeon_device *rdev) ...@@ -413,7 +414,7 @@ int rs600_gart_init(struct radeon_device *rdev)
{ {
int r; int r;
if (rdev->gart.table.vram.robj) { if (rdev->gart.robj) {
WARN(1, "RS600 GART already initialized\n"); WARN(1, "RS600 GART already initialized\n");
return 0; return 0;
} }
...@@ -431,7 +432,7 @@ static int rs600_gart_enable(struct radeon_device *rdev) ...@@ -431,7 +432,7 @@ static int rs600_gart_enable(struct radeon_device *rdev)
u32 tmp; u32 tmp;
int r, i; int r, i;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -494,20 +495,12 @@ static int rs600_gart_enable(struct radeon_device *rdev) ...@@ -494,20 +495,12 @@ static int rs600_gart_enable(struct radeon_device *rdev)
void rs600_gart_disable(struct radeon_device *rdev) void rs600_gart_disable(struct radeon_device *rdev)
{ {
u32 tmp; u32 tmp;
int r;
/* FIXME: disable out of gart access */ /* FIXME: disable out of gart access */
WREG32_MC(R_000100_MC_PT0_CNTL, 0); WREG32_MC(R_000100_MC_PT0_CNTL, 0);
tmp = RREG32_MC(R_000009_MC_CNTL1); tmp = RREG32_MC(R_000009_MC_CNTL1);
WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES); WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (r == 0) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void rs600_gart_fini(struct radeon_device *rdev) void rs600_gart_fini(struct radeon_device *rdev)
...@@ -525,7 +518,7 @@ void rs600_gart_fini(struct radeon_device *rdev) ...@@ -525,7 +518,7 @@ void rs600_gart_fini(struct radeon_device *rdev)
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; void __iomem *ptr = (void *)rdev->gart.ptr;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
......
...@@ -124,7 +124,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) ...@@ -124,7 +124,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
u32 tmp; u32 tmp;
int r, i; int r, i;
if (rdev->gart.table.vram.robj == NULL) { if (rdev->gart.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -171,7 +171,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) ...@@ -171,7 +171,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
void rv770_pcie_gart_disable(struct radeon_device *rdev) void rv770_pcie_gart_disable(struct radeon_device *rdev)
{ {
u32 tmp; u32 tmp;
int i, r; int i;
/* Disable all tables */ /* Disable all tables */
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++)
...@@ -191,14 +191,7 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev) ...@@ -191,14 +191,7 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
if (rdev->gart.table.vram.robj) { radeon_gart_table_vram_unpin(rdev);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
} }
void rv770_pcie_gart_fini(struct radeon_device *rdev) void rv770_pcie_gart_fini(struct radeon_device *rdev)
...@@ -282,7 +275,7 @@ static void rv770_mc_program(struct radeon_device *rdev) ...@@ -282,7 +275,7 @@ static void rv770_mc_program(struct radeon_device *rdev)
WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
rdev->mc.vram_end >> 12); rdev->mc.vram_end >> 12);
} }
WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
WREG32(MC_VM_FB_LOCATION, tmp); WREG32(MC_VM_FB_LOCATION, tmp);
...@@ -959,54 +952,6 @@ static void rv770_gpu_init(struct radeon_device *rdev) ...@@ -959,54 +952,6 @@ static void rv770_gpu_init(struct radeon_device *rdev)
} }
static int rv770_vram_scratch_init(struct radeon_device *rdev)
{
int r;
u64 gpu_addr;
if (rdev->vram_scratch.robj == NULL) {
r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
&rdev->vram_scratch.robj);
if (r) {
return r;
}
}
r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->vram_scratch.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->vram_scratch.robj);
return r;
}
r = radeon_bo_kmap(rdev->vram_scratch.robj,
(void **)&rdev->vram_scratch.ptr);
if (r)
radeon_bo_unpin(rdev->vram_scratch.robj);
radeon_bo_unreserve(rdev->vram_scratch.robj);
return r;
}
static void rv770_vram_scratch_fini(struct radeon_device *rdev)
{
int r;
if (rdev->vram_scratch.robj == NULL) {
return;
}
r = radeon_bo_reserve(rdev->vram_scratch.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->vram_scratch.robj);
radeon_bo_unpin(rdev->vram_scratch.robj);
radeon_bo_unreserve(rdev->vram_scratch.robj);
}
radeon_bo_unref(&rdev->vram_scratch.robj);
}
void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
{ {
u64 size_bf, size_af; u64 size_bf, size_af;
...@@ -1106,6 +1051,10 @@ static int rv770_startup(struct radeon_device *rdev) ...@@ -1106,6 +1051,10 @@ static int rv770_startup(struct radeon_device *rdev)
} }
} }
r = r600_vram_scratch_init(rdev);
if (r)
return r;
rv770_mc_program(rdev); rv770_mc_program(rdev);
if (rdev->flags & RADEON_IS_AGP) { if (rdev->flags & RADEON_IS_AGP) {
rv770_agp_enable(rdev); rv770_agp_enable(rdev);
...@@ -1114,9 +1063,7 @@ static int rv770_startup(struct radeon_device *rdev) ...@@ -1114,9 +1063,7 @@ static int rv770_startup(struct radeon_device *rdev)
if (r) if (r)
return r; return r;
} }
r = rv770_vram_scratch_init(rdev);
if (r)
return r;
rv770_gpu_init(rdev); rv770_gpu_init(rdev);
r = r600_blit_init(rdev); r = r600_blit_init(rdev);
if (r) { if (r) {
...@@ -1316,7 +1263,7 @@ void rv770_fini(struct radeon_device *rdev) ...@@ -1316,7 +1263,7 @@ void rv770_fini(struct radeon_device *rdev)
radeon_ib_pool_fini(rdev); radeon_ib_pool_fini(rdev);
radeon_irq_kms_fini(rdev); radeon_irq_kms_fini(rdev);
rv770_pcie_gart_fini(rdev); rv770_pcie_gart_fini(rdev);
rv770_vram_scratch_fini(rdev); r600_vram_scratch_fini(rdev);
radeon_gem_fini(rdev); radeon_gem_fini(rdev);
radeon_fence_driver_fini(rdev); radeon_fence_driver_fini(rdev);
radeon_agp_fini(rdev); radeon_agp_fini(rdev);
......
...@@ -104,6 +104,9 @@ ...@@ -104,6 +104,9 @@
#define DRM_IOCTL_VMW_PRESENT_READBACK \ #define DRM_IOCTL_VMW_PRESENT_READBACK \
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
struct drm_vmw_present_readback_arg) struct drm_vmw_present_readback_arg)
#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
struct drm_vmw_update_layout_arg)
/** /**
* The core DRM version of this macro doesn't account for * The core DRM version of this macro doesn't account for
...@@ -166,6 +169,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = { ...@@ -166,6 +169,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
VMW_IOCTL_DEF(VMW_PRESENT_READBACK, VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
vmw_present_readback_ioctl, vmw_present_readback_ioctl,
DRM_MASTER | DRM_AUTH | DRM_UNLOCKED), DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
vmw_kms_update_layout_ioctl,
DRM_MASTER | DRM_UNLOCKED),
}; };
static struct pci_device_id vmw_pci_id_list[] = { static struct pci_device_id vmw_pci_id_list[] = {
......
...@@ -40,9 +40,9 @@ ...@@ -40,9 +40,9 @@
#include "ttm/ttm_module.h" #include "ttm/ttm_module.h"
#include "vmwgfx_fence.h" #include "vmwgfx_fence.h"
#define VMWGFX_DRIVER_DATE "20111008" #define VMWGFX_DRIVER_DATE "20111025"
#define VMWGFX_DRIVER_MAJOR 2 #define VMWGFX_DRIVER_MAJOR 2
#define VMWGFX_DRIVER_MINOR 2 #define VMWGFX_DRIVER_MINOR 3
#define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_DRIVER_PATCHLEVEL 0
#define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024) #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
...@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv, ...@@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_vmw_fence_rep __user *user_fence_rep, struct drm_vmw_fence_rep __user *user_fence_rep,
struct drm_vmw_rect *clips, struct drm_vmw_rect *clips,
uint32_t num_clips); uint32_t num_clips);
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
/** /**
* Overlay control - vmwgfx_overlay.c * Overlay control - vmwgfx_overlay.c
......
...@@ -111,6 +111,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -111,6 +111,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
if (!ret) { if (!ret) {
if (!surface->snooper.image) { if (!surface->snooper.image) {
DRM_ERROR("surface not suitable for cursor\n"); DRM_ERROR("surface not suitable for cursor\n");
vmw_surface_unreference(&surface);
return -EINVAL; return -EINVAL;
} }
} else { } else {
...@@ -176,7 +177,9 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -176,7 +177,9 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
return 0; return 0;
} }
vmw_cursor_update_position(dev_priv, true, du->cursor_x, du->cursor_y); vmw_cursor_update_position(dev_priv, true,
du->cursor_x + du->hotspot_x,
du->cursor_y + du->hotspot_y);
return 0; return 0;
} }
...@@ -191,7 +194,8 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ...@@ -191,7 +194,8 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
du->cursor_y = y + crtc->y; du->cursor_y = y + crtc->y;
vmw_cursor_update_position(dev_priv, shown, vmw_cursor_update_position(dev_priv, shown,
du->cursor_x, du->cursor_y); du->cursor_x + du->hotspot_x,
du->cursor_y + du->hotspot_y);
return 0; return 0;
} }
...@@ -212,7 +216,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, ...@@ -212,7 +216,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
SVGA3dCmdHeader header; SVGA3dCmdHeader header;
SVGA3dCmdSurfaceDMA dma; SVGA3dCmdSurfaceDMA dma;
} *cmd; } *cmd;
int ret; int i, ret;
cmd = container_of(header, struct vmw_dma_cmd, header); cmd = container_of(header, struct vmw_dma_cmd, header);
...@@ -234,16 +238,19 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, ...@@ -234,16 +238,19 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) / box_count = (cmd->header.size - sizeof(SVGA3dCmdSurfaceDMA)) /
sizeof(SVGA3dCopyBox); sizeof(SVGA3dCopyBox);
if (cmd->dma.guest.pitch != (64 * 4) || if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
cmd->dma.guest.ptr.offset % PAGE_SIZE ||
box->x != 0 || box->y != 0 || box->z != 0 || box->x != 0 || box->y != 0 || box->z != 0 ||
box->srcx != 0 || box->srcy != 0 || box->srcz != 0 || box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
box->w != 64 || box->h != 64 || box->d != 1 || box->d != 1 || box_count != 1) {
box_count != 1) {
/* TODO handle none page aligned offsets */ /* TODO handle none page aligned offsets */
/* TODO handle partial uploads and pitch != 256 */ /* TODO handle more dst & src != 0 */
/* TODO handle more then one copy (size != 64) */ /* TODO handle more then one copy */
DRM_ERROR("lazy programmer, can't handle weird stuff\n"); DRM_ERROR("Cant snoop dma request for cursor!\n");
DRM_ERROR("(%u, %u, %u) (%u, %u, %u) (%ux%ux%u) %u %u\n",
box->srcx, box->srcy, box->srcz,
box->x, box->y, box->z,
box->w, box->h, box->d, box_count,
cmd->dma.guest.ptr.offset);
return; return;
} }
...@@ -262,7 +269,16 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, ...@@ -262,7 +269,16 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
virtual = ttm_kmap_obj_virtual(&map, &dummy); virtual = ttm_kmap_obj_virtual(&map, &dummy);
if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
memcpy(srf->snooper.image, virtual, 64*64*4); memcpy(srf->snooper.image, virtual, 64*64*4);
} else {
/* Image is unsigned pointer. */
for (i = 0; i < box->h; i++)
memcpy(srf->snooper.image + i * 64,
virtual + i * cmd->dma.guest.pitch,
box->w * 4);
}
srf->snooper.age++; srf->snooper.age++;
/* we can't call this function from this function since execbuf has /* we can't call this function from this function since execbuf has
...@@ -994,7 +1010,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, ...@@ -994,7 +1010,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
required_size = mode_cmd->pitch * mode_cmd->height; required_size = mode_cmd->pitch * mode_cmd->height;
if (unlikely(required_size > (u64) dev_priv->vram_size)) { if (unlikely(required_size > (u64) dev_priv->vram_size)) {
DRM_ERROR("VRAM size is too small for requested mode.\n"); DRM_ERROR("VRAM size is too small for requested mode.\n");
return NULL; return ERR_PTR(-ENOMEM);
} }
/* /*
...@@ -1517,6 +1533,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, ...@@ -1517,6 +1533,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
du->pref_width = rects[du->unit].w; du->pref_width = rects[du->unit].w;
du->pref_height = rects[du->unit].h; du->pref_height = rects[du->unit].h;
du->pref_active = true; du->pref_active = true;
du->gui_x = rects[du->unit].x;
du->gui_y = rects[du->unit].y;
} else { } else {
du->pref_width = 800; du->pref_width = 800;
du->pref_height = 600; du->pref_height = 600;
...@@ -1572,12 +1590,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force) ...@@ -1572,12 +1590,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
uint32_t num_displays; uint32_t num_displays;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct vmw_private *dev_priv = vmw_priv(dev); struct vmw_private *dev_priv = vmw_priv(dev);
struct vmw_display_unit *du = vmw_connector_to_du(connector);
mutex_lock(&dev_priv->hw_mutex); mutex_lock(&dev_priv->hw_mutex);
num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
mutex_unlock(&dev_priv->hw_mutex); mutex_unlock(&dev_priv->hw_mutex);
return ((vmw_connector_to_du(connector)->unit < num_displays) ? return ((vmw_connector_to_du(connector)->unit < num_displays &&
du->pref_active) ?
connector_status_connected : connector_status_disconnected); connector_status_connected : connector_status_disconnected);
} }
...@@ -1658,6 +1678,28 @@ static struct drm_display_mode vmw_kms_connector_builtin[] = { ...@@ -1658,6 +1678,28 @@ static struct drm_display_mode vmw_kms_connector_builtin[] = {
{ DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }, { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) },
}; };
/**
* vmw_guess_mode_timing - Provide fake timings for a
* 60Hz vrefresh mode.
*
* @mode - Pointer to a struct drm_display_mode with hdisplay and vdisplay
* members filled in.
*/
static void vmw_guess_mode_timing(struct drm_display_mode *mode)
{
mode->hsync_start = mode->hdisplay + 50;
mode->hsync_end = mode->hsync_start + 50;
mode->htotal = mode->hsync_end + 50;
mode->vsync_start = mode->vdisplay + 50;
mode->vsync_end = mode->vsync_start + 50;
mode->vtotal = mode->vsync_end + 50;
mode->clock = (u32)mode->htotal * (u32)mode->vtotal / 100 * 6;
mode->vrefresh = drm_mode_vrefresh(mode);
}
int vmw_du_connector_fill_modes(struct drm_connector *connector, int vmw_du_connector_fill_modes(struct drm_connector *connector,
uint32_t max_width, uint32_t max_height) uint32_t max_width, uint32_t max_height)
{ {
...@@ -1680,19 +1722,24 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, ...@@ -1680,19 +1722,24 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
return 0; return 0;
mode->hdisplay = du->pref_width; mode->hdisplay = du->pref_width;
mode->vdisplay = du->pref_height; mode->vdisplay = du->pref_height;
mode->vrefresh = drm_mode_vrefresh(mode); vmw_guess_mode_timing(mode);
if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2,
mode->vdisplay)) { mode->vdisplay)) {
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
} else {
drm_mode_destroy(dev, mode);
mode = NULL;
}
if (du->pref_mode) { if (du->pref_mode) {
list_del_init(&du->pref_mode->head); list_del_init(&du->pref_mode->head);
drm_mode_destroy(dev, du->pref_mode); drm_mode_destroy(dev, du->pref_mode);
} }
/* mode might be null here, this is intended */
du->pref_mode = mode; du->pref_mode = mode;
} }
}
for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) { for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) {
bmode = &vmw_kms_connector_builtin[i]; bmode = &vmw_kms_connector_builtin[i];
...@@ -1712,6 +1759,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, ...@@ -1712,6 +1759,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
} }
/* Move the prefered mode first, help apps pick the right mode. */
if (du->pref_mode)
list_move(&du->pref_mode->head, &connector->probed_modes);
drm_mode_connector_list_update(connector); drm_mode_connector_list_update(connector);
return 1; return 1;
...@@ -1723,3 +1774,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector, ...@@ -1723,3 +1774,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
{ {
return 0; return 0;
} }
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct vmw_private *dev_priv = vmw_priv(dev);
struct drm_vmw_update_layout_arg *arg =
(struct drm_vmw_update_layout_arg *)data;
struct vmw_master *vmaster = vmw_master(file_priv->master);
void __user *user_rects;
struct drm_vmw_rect *rects;
unsigned rects_size;
int ret;
int i;
struct drm_mode_config *mode_config = &dev->mode_config;
ret = ttm_read_lock(&vmaster->lock, true);
if (unlikely(ret != 0))
return ret;
if (!arg->num_outputs) {
struct drm_vmw_rect def_rect = {0, 0, 800, 600};
vmw_du_update_layout(dev_priv, 1, &def_rect);
goto out_unlock;
}
rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
rects = kzalloc(rects_size, GFP_KERNEL);
if (unlikely(!rects)) {
ret = -ENOMEM;
goto out_unlock;
}
user_rects = (void __user *)(unsigned long)arg->rects;
ret = copy_from_user(rects, user_rects, rects_size);
if (unlikely(ret != 0)) {
DRM_ERROR("Failed to get rects.\n");
ret = -EFAULT;
goto out_free;
}
for (i = 0; i < arg->num_outputs; ++i) {
if (rects->x < 0 ||
rects->y < 0 ||
rects->x + rects->w > mode_config->max_width ||
rects->y + rects->h > mode_config->max_height) {
DRM_ERROR("Invalid GUI layout.\n");
ret = -EINVAL;
goto out_free;
}
}
vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
out_free:
kfree(rects);
out_unlock:
ttm_read_unlock(&vmaster->lock);
return ret;
}
...@@ -96,6 +96,13 @@ struct vmw_display_unit { ...@@ -96,6 +96,13 @@ struct vmw_display_unit {
unsigned pref_height; unsigned pref_height;
bool pref_active; bool pref_active;
struct drm_display_mode *pref_mode; struct drm_display_mode *pref_mode;
/*
* Gui positioning
*/
int gui_x;
int gui_y;
bool is_implicit;
}; };
#define vmw_crtc_to_du(x) \ #define vmw_crtc_to_du(x) \
...@@ -126,8 +133,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector, ...@@ -126,8 +133,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
int vmw_du_connector_set_property(struct drm_connector *connector, int vmw_du_connector_set_property(struct drm_connector *connector,
struct drm_property *property, struct drm_property *property,
uint64_t val); uint64_t val);
int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
struct drm_vmw_rect *rects);
/* /*
* Legacy display unit functions - vmwgfx_ldu.c * Legacy display unit functions - vmwgfx_ldu.c
......
...@@ -337,13 +337,14 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) ...@@ -337,13 +337,14 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
ldu->base.pref_width = 800; ldu->base.pref_width = 800;
ldu->base.pref_height = 600; ldu->base.pref_height = 600;
ldu->base.pref_mode = NULL; ldu->base.pref_mode = NULL;
ldu->base.is_implicit = true;
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
DRM_MODE_CONNECTOR_LVDS); DRM_MODE_CONNECTOR_VIRTUAL);
connector->status = vmw_du_connector_detect(connector, true); connector->status = vmw_du_connector_detect(connector, true);
drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
DRM_MODE_ENCODER_LVDS); DRM_MODE_ENCODER_VIRTUAL);
drm_mode_connector_attach_encoder(connector, encoder); drm_mode_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = (1 << unit); encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0; encoder->possible_clones = 0;
......
...@@ -36,12 +36,9 @@ ...@@ -36,12 +36,9 @@
container_of(x, struct vmw_screen_object_unit, base.connector) container_of(x, struct vmw_screen_object_unit, base.connector)
struct vmw_screen_object_display { struct vmw_screen_object_display {
struct list_head active; unsigned num_implicit;
unsigned num_active; struct vmw_framebuffer *implicit_fb;
unsigned last_num_active;
struct vmw_framebuffer *fb;
}; };
/** /**
...@@ -54,13 +51,11 @@ struct vmw_screen_object_unit { ...@@ -54,13 +51,11 @@ struct vmw_screen_object_unit {
struct vmw_dma_buffer *buffer; /**< Backing store buffer */ struct vmw_dma_buffer *buffer; /**< Backing store buffer */
bool defined; bool defined;
bool active_implicit;
struct list_head active;
}; };
static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) static void vmw_sou_destroy(struct vmw_screen_object_unit *sou)
{ {
list_del_init(&sou->active);
vmw_display_unit_cleanup(&sou->base); vmw_display_unit_cleanup(&sou->base);
kfree(sou); kfree(sou);
} }
...@@ -75,58 +70,31 @@ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc) ...@@ -75,58 +70,31 @@ static void vmw_sou_crtc_destroy(struct drm_crtc *crtc)
vmw_sou_destroy(vmw_crtc_to_sou(crtc)); vmw_sou_destroy(vmw_crtc_to_sou(crtc));
} }
static int vmw_sou_del_active(struct vmw_private *vmw_priv, static void vmw_sou_del_active(struct vmw_private *vmw_priv,
struct vmw_screen_object_unit *sou) struct vmw_screen_object_unit *sou)
{ {
struct vmw_screen_object_display *ld = vmw_priv->sou_priv; struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
if (list_empty(&sou->active))
return 0;
/* Must init otherwise list_empty(&sou->active) will not work. */ if (sou->active_implicit) {
list_del_init(&sou->active); if (--(ld->num_implicit) == 0)
if (--(ld->num_active) == 0) { ld->implicit_fb = NULL;
BUG_ON(!ld->fb); sou->active_implicit = false;
if (ld->fb->unpin)
ld->fb->unpin(ld->fb);
ld->fb = NULL;
} }
return 0;
} }
static int vmw_sou_add_active(struct vmw_private *vmw_priv, static void vmw_sou_add_active(struct vmw_private *vmw_priv,
struct vmw_screen_object_unit *sou, struct vmw_screen_object_unit *sou,
struct vmw_framebuffer *vfb) struct vmw_framebuffer *vfb)
{ {
struct vmw_screen_object_display *ld = vmw_priv->sou_priv; struct vmw_screen_object_display *ld = vmw_priv->sou_priv;
struct vmw_screen_object_unit *entry;
struct list_head *at;
BUG_ON(!ld->num_active && ld->fb);
if (vfb != ld->fb) {
if (ld->fb && ld->fb->unpin)
ld->fb->unpin(ld->fb);
if (vfb->pin)
vfb->pin(vfb);
ld->fb = vfb;
}
if (!list_empty(&sou->active))
return 0;
at = &ld->active; BUG_ON(!ld->num_implicit && ld->implicit_fb);
list_for_each_entry(entry, &ld->active, active) {
if (entry->base.unit > sou->base.unit)
break;
at = &entry->active; if (!sou->active_implicit && sou->base.is_implicit) {
ld->implicit_fb = vfb;
sou->active_implicit = true;
ld->num_implicit++;
} }
list_add(&sou->active, at);
ld->num_active++;
return 0;
} }
/** /**
...@@ -164,8 +132,13 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv, ...@@ -164,8 +132,13 @@ static int vmw_sou_fifo_create(struct vmw_private *dev_priv,
(sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0); (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0);
cmd->obj.size.width = mode->hdisplay; cmd->obj.size.width = mode->hdisplay;
cmd->obj.size.height = mode->vdisplay; cmd->obj.size.height = mode->vdisplay;
if (sou->base.is_implicit) {
cmd->obj.root.x = x; cmd->obj.root.x = x;
cmd->obj.root.y = y; cmd->obj.root.y = y;
} else {
cmd->obj.root.x = sou->base.gui_x;
cmd->obj.root.y = sou->base.gui_y;
}
/* Ok to assume that buffer is pinned in vram */ /* Ok to assume that buffer is pinned in vram */
vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr);
...@@ -312,10 +285,11 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set) ...@@ -312,10 +285,11 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
} }
/* sou only supports one fb active at the time */ /* sou only supports one fb active at the time */
if (dev_priv->sou_priv->fb && vfb && if (sou->base.is_implicit &&
!(dev_priv->sou_priv->num_active == 1 && dev_priv->sou_priv->implicit_fb && vfb &&
!list_empty(&sou->active)) && !(dev_priv->sou_priv->num_implicit == 1 &&
dev_priv->sou_priv->fb != vfb) { sou->active_implicit) &&
dev_priv->sou_priv->implicit_fb != vfb) {
DRM_ERROR("Multiple framebuffers not supported\n"); DRM_ERROR("Multiple framebuffers not supported\n");
return -EINVAL; return -EINVAL;
} }
...@@ -471,19 +445,20 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) ...@@ -471,19 +445,20 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
encoder = &sou->base.encoder; encoder = &sou->base.encoder;
connector = &sou->base.connector; connector = &sou->base.connector;
INIT_LIST_HEAD(&sou->active); sou->active_implicit = false;
sou->base.pref_active = (unit == 0); sou->base.pref_active = (unit == 0);
sou->base.pref_width = 800; sou->base.pref_width = 800;
sou->base.pref_height = 600; sou->base.pref_height = 600;
sou->base.pref_mode = NULL; sou->base.pref_mode = NULL;
sou->base.is_implicit = true;
drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
DRM_MODE_CONNECTOR_LVDS); DRM_MODE_CONNECTOR_VIRTUAL);
connector->status = vmw_du_connector_detect(connector, true); connector->status = vmw_du_connector_detect(connector, true);
drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
DRM_MODE_ENCODER_LVDS); DRM_MODE_ENCODER_VIRTUAL);
drm_mode_connector_attach_encoder(connector, encoder); drm_mode_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = (1 << unit); encoder->possible_crtcs = (1 << unit);
encoder->possible_clones = 0; encoder->possible_clones = 0;
...@@ -520,10 +495,8 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv) ...@@ -520,10 +495,8 @@ int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv)
if (unlikely(!dev_priv->sou_priv)) if (unlikely(!dev_priv->sou_priv))
goto err_no_mem; goto err_no_mem;
INIT_LIST_HEAD(&dev_priv->sou_priv->active); dev_priv->sou_priv->num_implicit = 0;
dev_priv->sou_priv->num_active = 0; dev_priv->sou_priv->implicit_fb = NULL;
dev_priv->sou_priv->last_num_active = 0;
dev_priv->sou_priv->fb = NULL;
ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
...@@ -558,9 +531,6 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) ...@@ -558,9 +531,6 @@ int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv)
drm_vblank_cleanup(dev); drm_vblank_cleanup(dev);
if (!list_empty(&dev_priv->sou_priv->active))
DRM_ERROR("Still have active outputs when unloading driver");
kfree(dev_priv->sou_priv); kfree(dev_priv->sou_priv);
return 0; return 0;
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#define DP_MAIN_LINK_CHANNEL_CODING 0x006 #define DP_MAIN_LINK_CHANNEL_CODING 0x006
#define DP_EDP_CONFIGURATION_CAP 0x00d
#define DP_TRAINING_AUX_RD_INTERVAL 0x00e #define DP_TRAINING_AUX_RD_INTERVAL 0x00e
#define DP_PSR_SUPPORT 0x070 #define DP_PSR_SUPPORT 0x070
...@@ -159,6 +160,8 @@ ...@@ -159,6 +160,8 @@
# define DP_CP_IRQ (1 << 2) # define DP_CP_IRQ (1 << 2)
# define DP_SINK_SPECIFIC_IRQ (1 << 6) # define DP_SINK_SPECIFIC_IRQ (1 << 6)
#define DP_EDP_CONFIGURATION_SET 0x10a
#define DP_LANE0_1_STATUS 0x202 #define DP_LANE0_1_STATUS 0x202
#define DP_LANE2_3_STATUS 0x203 #define DP_LANE2_3_STATUS 0x203
# define DP_LANE_CR_DONE (1 << 0) # define DP_LANE_CR_DONE (1 << 0)
......
...@@ -125,6 +125,7 @@ struct drm_mode_crtc { ...@@ -125,6 +125,7 @@ struct drm_mode_crtc {
#define DRM_MODE_ENCODER_TMDS 2 #define DRM_MODE_ENCODER_TMDS 2
#define DRM_MODE_ENCODER_LVDS 3 #define DRM_MODE_ENCODER_LVDS 3
#define DRM_MODE_ENCODER_TVDAC 4 #define DRM_MODE_ENCODER_TVDAC 4
#define DRM_MODE_ENCODER_VIRTUAL 5
struct drm_mode_get_encoder { struct drm_mode_get_encoder {
__u32 encoder_id; __u32 encoder_id;
...@@ -162,6 +163,7 @@ struct drm_mode_get_encoder { ...@@ -162,6 +163,7 @@ struct drm_mode_get_encoder {
#define DRM_MODE_CONNECTOR_HDMIB 12 #define DRM_MODE_CONNECTOR_HDMIB 12
#define DRM_MODE_CONNECTOR_TV 13 #define DRM_MODE_CONNECTOR_TV 13
#define DRM_MODE_CONNECTOR_eDP 14 #define DRM_MODE_CONNECTOR_eDP 14
#define DRM_MODE_CONNECTOR_VIRTUAL 15
struct drm_mode_get_connector { struct drm_mode_get_connector {
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#define DRM_VMW_FENCE_EVENT 17 #define DRM_VMW_FENCE_EVENT 17
#define DRM_VMW_PRESENT 18 #define DRM_VMW_PRESENT 18
#define DRM_VMW_PRESENT_READBACK 19 #define DRM_VMW_PRESENT_READBACK 19
#define DRM_VMW_UPDATE_LAYOUT 20
/*************************************************************************/ /*************************************************************************/
/** /**
...@@ -550,31 +550,6 @@ struct drm_vmw_get_3d_cap_arg { ...@@ -550,31 +550,6 @@ struct drm_vmw_get_3d_cap_arg {
uint32_t pad64; uint32_t pad64;
}; };
/*************************************************************************/
/**
* DRM_VMW_UPDATE_LAYOUT - Update layout
*
* Updates the preferred modes and connection status for connectors. The
* command conisits of one drm_vmw_update_layout_arg pointing out a array
* of num_outputs drm_vmw_rect's.
*/
/**
* struct drm_vmw_update_layout_arg
*
* @num_outputs: number of active
* @rects: pointer to array of drm_vmw_rect
*
* Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
*/
struct drm_vmw_update_layout_arg {
uint32_t num_outputs;
uint32_t pad64;
uint64_t rects;
};
/*************************************************************************/ /*************************************************************************/
/** /**
* DRM_VMW_FENCE_WAIT * DRM_VMW_FENCE_WAIT
...@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg { ...@@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
uint64_t clips_ptr; uint64_t clips_ptr;
uint64_t fence_rep; uint64_t fence_rep;
}; };
/*************************************************************************/
/**
* DRM_VMW_UPDATE_LAYOUT - Update layout
*
* Updates the preferred modes and connection status for connectors. The
* command consists of one drm_vmw_update_layout_arg pointing to an array
* of num_outputs drm_vmw_rect's.
*/
/**
* struct drm_vmw_update_layout_arg
*
* @num_outputs: number of active connectors
* @rects: pointer to array of drm_vmw_rect cast to an uint64_t
*
* Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
*/
struct drm_vmw_update_layout_arg {
uint32_t num_outputs;
uint32_t pad64;
uint64_t rects;
};
#endif #endif
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