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 ...
This commit is contained in:
commit
83dbb15e9c
@ -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[] =
|
|||||||
{ 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,
|
|||||||
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++;
|
||||||
|
|
||||||
drm_connector_attach_property(connector,
|
if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
|
||||||
dev->mode_config.edid_property, 0);
|
drm_connector_attach_property(connector,
|
||||||
|
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 \
|
|||||||
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,
|
|||||||
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,44 +638,29 @@ 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)) {
|
args.v3.sInput.ucDispPllConfig |=
|
||||||
|
DISPPLL_CONFIG_COHERENT_MODE;
|
||||||
|
/* 16200 or 27000 */
|
||||||
|
args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
|
||||||
|
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
|
||||||
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
|
||||||
if (encoder_mode == ATOM_ENCODER_MODE_DP) {
|
if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
|
||||||
|
/* deep color support */
|
||||||
|
args.v3.sInput.usPixelClock =
|
||||||
|
cpu_to_le16((mode->clock * bpc / 8) / 10);
|
||||||
|
if (dig->coherent_mode)
|
||||||
args.v3.sInput.ucDispPllConfig |=
|
args.v3.sInput.ucDispPllConfig |=
|
||||||
DISPPLL_CONFIG_COHERENT_MODE;
|
DISPPLL_CONFIG_COHERENT_MODE;
|
||||||
/* 16200 or 27000 */
|
if (mode->clock > 165000)
|
||||||
args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
|
|
||||||
} else {
|
|
||||||
if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
|
|
||||||
/* deep color support */
|
|
||||||
args.v3.sInput.usPixelClock =
|
|
||||||
cpu_to_le16((mode->clock * bpc / 8) / 10);
|
|
||||||
}
|
|
||||||
if (dig->coherent_mode)
|
|
||||||
args.v3.sInput.ucDispPllConfig |=
|
|
||||||
DISPPLL_CONFIG_COHERENT_MODE;
|
|
||||||
if (mode->clock > 165000)
|
|
||||||
args.v3.sInput.ucDispPllConfig |=
|
|
||||||
DISPPLL_CONFIG_DUAL_LINK;
|
|
||||||
}
|
|
||||||
} else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
|
|
||||||
if (encoder_mode == ATOM_ENCODER_MODE_DP) {
|
|
||||||
args.v3.sInput.ucDispPllConfig |=
|
args.v3.sInput.ucDispPllConfig |=
|
||||||
DISPPLL_CONFIG_COHERENT_MODE;
|
DISPPLL_CONFIG_DUAL_LINK;
|
||||||
/* 16200 or 27000 */
|
|
||||||
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)) {
|
if (radeon_encoder_get_dp_bridge_encoder_id(encoder) !=
|
||||||
struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
|
ENCODER_OBJECT_ID_NONE)
|
||||||
struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
|
args.v3.sInput.ucExtTransmitterID =
|
||||||
args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
|
radeon_encoder_get_dp_bridge_encoder_id(encoder);
|
||||||
} else
|
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
|
|||||||
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)
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
||||||
|
2369
drivers/gpu/drm/radeon/atombios_encoders.c
Normal file
2369
drivers/gpu/drm/radeon/atombios_encoders.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
struct drm_device *dev = rdev->ddev;
|
struct drm_device *dev = rdev->ddev;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
|
||||||
if (ASIC_IS_DCE3(rdev)) {
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||||
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
|
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||||
if (ASIC_IS_DCE32(rdev))
|
|
||||||
tmp |= DC_HPDx_EN;
|
if (ASIC_IS_DCE3(rdev)) {
|
||||||
|
u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa);
|
||||||
|
if (ASIC_IS_DCE32(rdev))
|
||||||
|
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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;
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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);
|
|||||||
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,
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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,
|
|||||||
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 {
|
|||||||
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);
|
|||||||
/* 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);
|
|||||||
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
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
} 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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;
|
|||||||
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);
|
|||||||
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;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -151,12 +159,14 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
|
|||||||
if (rdev->gart.pages[p]) {
|
if (rdev->gart.pages[p]) {
|
||||||
if (!rdev->gart.ttm_alloced[p])
|
if (!rdev->gart.ttm_alloced[p])
|
||||||
pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
|
pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
|
||||||
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
|
||||||
rdev->gart.pages[p] = NULL;
|
rdev->gart.pages[p] = NULL;
|
||||||
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++) {
|
||||||
radeon_gart_set_page(rdev, t, page_base);
|
if (rdev->gart.ptr) {
|
||||||
|
radeon_gart_set_page(rdev, t, page_base);
|
||||||
|
}
|
||||||
page_base += RADEON_GPU_PAGE_SIZE;
|
page_base += RADEON_GPU_PAGE_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,10 +209,12 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
rdev->gart.pages[p] = pagelist[i];
|
rdev->gart.pages[p] = pagelist[i];
|
||||||
page_base = rdev->gart.pages_addr[p];
|
if (rdev->gart.ptr) {
|
||||||
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
|
page_base = rdev->gart.pages_addr[p];
|
||||||
radeon_gart_set_page(rdev, t, page_base);
|
for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
|
||||||
page_base += RADEON_GPU_PAGE_SIZE;
|
radeon_gart_set_page(rdev, t, page_base);
|
||||||
|
page_base += RADEON_GPU_PAGE_SIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mb();
|
mb();
|
||||||
@ -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 @@
|
|||||||
* 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
|
|||||||
{
|
{
|
||||||
.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,17 +62,15 @@ 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.
|
* Only the first 6 bytes must be valid as
|
||||||
* Only the first 6 bytes must be valid as
|
* drm_edid_block_valid() can fix the last 2 bytes */
|
||||||
* drm_edid_block_valid() can fix the last 2 bytes */
|
if (drm_edid_header_is_valid(buf) < 6) {
|
||||||
if (drm_edid_header_is_valid(buf) < 6) {
|
/* Couldn't find an accessible EDID on this
|
||||||
/* Couldn't find an accessible EDID on this
|
* connector */
|
||||||
* connector */
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|||||||
/* 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)
|
|||||||
}
|
}
|
||||||
/* 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 {
|
|||||||
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 {
|
|||||||
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);
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
((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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
#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[] = {
|
|||||||
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 @@
|
|||||||
#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,
|
|||||||
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,
|
|||||||
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 @@ err_unreserve:
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
virtual = ttm_kmap_obj_virtual(&map, &dummy);
|
virtual = ttm_kmap_obj_virtual(&map, &dummy);
|
||||||
|
|
||||||
memcpy(srf->snooper.image, virtual, 64*64*4);
|
if (box->w == 64 && cmd->dma.guest.pitch == 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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[] = {
|
|||||||
{ 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,18 +1722,23 @@ 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 {
|
||||||
if (du->pref_mode) {
|
drm_mode_destroy(dev, mode);
|
||||||
list_del_init(&du->pref_mode->head);
|
mode = NULL;
|
||||||
drm_mode_destroy(dev, du->pref_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
du->pref_mode = mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (du->pref_mode) {
|
||||||
|
list_del_init(&du->pref_mode->head);
|
||||||
|
drm_mode_destroy(dev, du->pref_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mode might be null here, this is intended */
|
||||||
|
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++) {
|
||||||
@ -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,
|
|||||||
{
|
{
|
||||||
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 {
|
|||||||
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,
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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);
|
BUG_ON(!ld->num_implicit && ld->implicit_fb);
|
||||||
if (vfb != ld->fb) {
|
|
||||||
if (ld->fb && ld->fb->unpin)
|
if (!sou->active_implicit && sou->base.is_implicit) {
|
||||||
ld->fb->unpin(ld->fb);
|
ld->implicit_fb = vfb;
|
||||||
if (vfb->pin)
|
sou->active_implicit = true;
|
||||||
vfb->pin(vfb);
|
ld->num_implicit++;
|
||||||
ld->fb = vfb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list_empty(&sou->active))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
at = &ld->active;
|
|
||||||
list_for_each_entry(entry, &ld->active, active) {
|
|
||||||
if (entry->base.unit > sou->base.unit)
|
|
||||||
break;
|
|
||||||
|
|
||||||
at = &entry->active;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|||||||
(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;
|
||||||
cmd->obj.root.x = x;
|
if (sou->base.is_implicit) {
|
||||||
cmd->obj.root.y = y;
|
cmd->obj.root.x = x;
|
||||||
|
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 @@
|
|||||||
# 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)
|
||||||
|
@ -120,11 +120,12 @@ struct drm_mode_crtc {
|
|||||||
struct drm_mode_modeinfo mode;
|
struct drm_mode_modeinfo mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DRM_MODE_ENCODER_NONE 0
|
#define DRM_MODE_ENCODER_NONE 0
|
||||||
#define DRM_MODE_ENCODER_DAC 1
|
#define DRM_MODE_ENCODER_DAC 1
|
||||||
#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 {
|
|||||||
#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 @@
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user