mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: drm/radeon/kms: use helper functions for fence read/write drm/radeon/kms: set DP link config properly for DP bridges drm/radeon/kms/atom: AdjustPixelClock fixes for DP bridges drm/radeon/kms: fix handling of DP to LVDS bridges drm/radeon/kms: issue blank/unblank commands for ext encoders drm/radeon/kms: fix support for DDC on dp bridges drm/radeon/kms: add support for load detection on dp bridges drm/radeon/kms: add missing external encoder action drm/radeon/kms: rework atombios_get_encoder_mode() drm/radeon/kms: fix num crtcs for Cedar and Caicos Revert "drm/i915: Enable GMBUS for post-gen2 chipsets" drivers/gpu/drm: use printk_ratelimited instead of printk_ratelimit drm/radeon: workaround a hw bug on some radeon chipsets with all-0 EDIDs. drm: make debug levels match in edid failure code. drm/radeon/kms: clear wb memory by default drm/radeon/kms: be more pedantic about the g5 quirk (v2) drm/radeon/kms: signed fix for evergreen thermal drm: populate irq_by_busid-member for pci
This commit is contained in:
commit
eb96c92515
@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)
|
||||
|
||||
bad:
|
||||
if (raw_edid) {
|
||||
DRM_ERROR("Raw EDID:\n");
|
||||
printk(KERN_ERR "Raw EDID:\n");
|
||||
print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
|
||||
printk("\n");
|
||||
printk(KERN_ERR "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
|
||||
return ret == 2 ? 0 : -1;
|
||||
}
|
||||
|
||||
static bool drm_edid_is_zero(u8 *in_edid, int length)
|
||||
{
|
||||
int i;
|
||||
u32 *raw_edid = (u32 *)in_edid;
|
||||
|
||||
for (i = 0; i < length / 4; i++)
|
||||
if (*(raw_edid + i) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static u8 *
|
||||
drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
||||
{
|
||||
@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
|
||||
goto out;
|
||||
if (drm_edid_block_valid(block))
|
||||
break;
|
||||
if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
|
||||
connector->null_edid_counter++;
|
||||
goto carp;
|
||||
}
|
||||
}
|
||||
if (i == 4)
|
||||
goto carp;
|
||||
|
@ -28,6 +28,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#include <linux/compat.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include "drmP.h"
|
||||
#include "drm_core.h"
|
||||
@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
|
||||
return -EFAULT;
|
||||
|
||||
m32.handle = (unsigned long)handle;
|
||||
if (m32.handle != (unsigned long)handle && printk_ratelimit())
|
||||
printk(KERN_ERR "compat_drm_addmap truncated handle"
|
||||
" %p for type %d offset %x\n",
|
||||
handle, m32.type, m32.offset);
|
||||
if (m32.handle != (unsigned long)handle)
|
||||
printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
|
||||
" %p for type %d offset %x\n",
|
||||
handle, m32.type, m32.offset);
|
||||
|
||||
if (copy_to_user(argp, &m32, sizeof(m32)))
|
||||
return -EFAULT;
|
||||
|
@ -251,7 +251,7 @@ err:
|
||||
}
|
||||
|
||||
|
||||
int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
|
||||
static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
|
||||
{
|
||||
if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
|
||||
(p->busnum & 0xff) != dev->pdev->bus->number ||
|
||||
@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {
|
||||
.get_name = drm_pci_get_name,
|
||||
.set_busid = drm_pci_set_busid,
|
||||
.set_unique = drm_pci_set_unique,
|
||||
.irq_by_busid = drm_pci_irq_by_busid,
|
||||
.agp_init = drm_pci_agp_init,
|
||||
};
|
||||
|
||||
|
@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)
|
||||
bus->reg0 = i | GMBUS_RATE_100KHZ;
|
||||
|
||||
/* XXX force bit banging until GMBUS is fully debugged */
|
||||
if (IS_GEN2(dev))
|
||||
bus->force_bit = intel_gpio_create(dev_priv, i);
|
||||
bus->force_bit = intel_gpio_create(dev_priv, i);
|
||||
}
|
||||
|
||||
intel_i2c_reset(dev_priv->dev);
|
||||
|
@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3
|
||||
#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10
|
||||
#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11
|
||||
#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12
|
||||
#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP 0x14
|
||||
|
||||
// ucConfig
|
||||
#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03
|
||||
|
@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
|
||||
DISPPLL_CONFIG_DUAL_LINK;
|
||||
}
|
||||
}
|
||||
if (radeon_encoder_is_dp_bridge(encoder)) {
|
||||
struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
|
||||
struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
|
||||
args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
|
||||
} else
|
||||
args.v3.sInput.ucExtTransmitterID = 0;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context,
|
||||
index, (uint32_t *)&args);
|
||||
adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
|
||||
|
@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
|
||||
/* get temperature in millidegrees */
|
||||
int evergreen_get_temp(struct radeon_device *rdev)
|
||||
{
|
||||
u32 temp, toffset, actual_temp = 0;
|
||||
u32 temp, toffset;
|
||||
int actual_temp = 0;
|
||||
|
||||
if (rdev->family == CHIP_JUNIPER) {
|
||||
toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>
|
||||
|
@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = {
|
||||
int radeon_asic_init(struct radeon_device *rdev)
|
||||
{
|
||||
radeon_register_accessor_init(rdev);
|
||||
|
||||
/* set the number of crtcs */
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
rdev->num_crtc = 1;
|
||||
else
|
||||
rdev->num_crtc = 2;
|
||||
|
||||
switch (rdev->family) {
|
||||
case CHIP_R100:
|
||||
case CHIP_RV100:
|
||||
@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev)
|
||||
case CHIP_JUNIPER:
|
||||
case CHIP_CYPRESS:
|
||||
case CHIP_HEMLOCK:
|
||||
/* set num crtcs */
|
||||
if (rdev->family == CHIP_CEDAR)
|
||||
rdev->num_crtc = 4;
|
||||
else
|
||||
rdev->num_crtc = 6;
|
||||
rdev->asic = &evergreen_asic;
|
||||
break;
|
||||
case CHIP_PALM:
|
||||
@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev)
|
||||
case CHIP_BARTS:
|
||||
case CHIP_TURKS:
|
||||
case CHIP_CAICOS:
|
||||
/* set num crtcs */
|
||||
if (rdev->family == CHIP_CAICOS)
|
||||
rdev->num_crtc = 4;
|
||||
else
|
||||
rdev->num_crtc = 6;
|
||||
rdev->asic = &btc_asic;
|
||||
break;
|
||||
case CHIP_CAYMAN:
|
||||
rdev->asic = &cayman_asic;
|
||||
/* set num crtcs */
|
||||
rdev->num_crtc = 6;
|
||||
break;
|
||||
default:
|
||||
/* FIXME: not supported yet */
|
||||
@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev)
|
||||
rdev->asic->set_memory_clock = NULL;
|
||||
}
|
||||
|
||||
/* set the number of crtcs */
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
rdev->num_crtc = 1;
|
||||
else {
|
||||
if (ASIC_IS_DCE41(rdev))
|
||||
rdev->num_crtc = 2;
|
||||
else if (ASIC_IS_DCE4(rdev))
|
||||
rdev->num_crtc = 6;
|
||||
else
|
||||
rdev->num_crtc = 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1553,9 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
|
||||
(rdev->pdev->subsystem_device == 0x4a48)) {
|
||||
/* Mac X800 */
|
||||
rdev->mode_info.connector_table = CT_MAC_X800;
|
||||
} else if (of_machine_is_compatible("PowerMac7,2") ||
|
||||
of_machine_is_compatible("PowerMac7,3")) {
|
||||
/* Mac G5 9600 */
|
||||
} else if ((of_machine_is_compatible("PowerMac7,2") ||
|
||||
of_machine_is_compatible("PowerMac7,3")) &&
|
||||
(rdev->pdev->device == 0x4150) &&
|
||||
(rdev->pdev->subsystem_vendor == 0x1002) &&
|
||||
(rdev->pdev->subsystem_device == 0x4150)) {
|
||||
/* Mac G5 tower 9600 */
|
||||
rdev->mode_info.connector_table = CT_MAC_G5_9600;
|
||||
} else
|
||||
#endif /* CONFIG_PPC_PMAC */
|
||||
|
@ -44,6 +44,8 @@ extern void
|
||||
radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
|
||||
struct drm_connector *drm_connector);
|
||||
|
||||
bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
|
||||
|
||||
void radeon_connector_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
@ -836,6 +838,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
if (!radeon_connector->edid) {
|
||||
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
|
||||
drm_get_connector_name(connector));
|
||||
/* rs690 seems to have a problem with connectors not existing and always
|
||||
* return a block of 0's. If we see this just stop polling on this output */
|
||||
if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
|
||||
ret = connector_status_disconnected;
|
||||
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
|
||||
radeon_connector->ddc_bus = NULL;
|
||||
}
|
||||
} else {
|
||||
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
|
||||
@ -1063,10 +1072,11 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
int ret;
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
struct drm_encoder *encoder;
|
||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
if (!radeon_dig_connector->edp_on)
|
||||
@ -1078,7 +1088,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
|
||||
ATOM_TRANSMITTER_ACTION_POWER_OFF);
|
||||
|
||||
if (ret > 0) {
|
||||
encoder = radeon_best_single_encoder(connector);
|
||||
if (encoder) {
|
||||
radeon_fixup_lvds_native_mode(encoder, connector);
|
||||
/* add scaled modes */
|
||||
@ -1102,8 +1111,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
|
||||
/* add scaled modes */
|
||||
radeon_add_common_modes(encoder, connector);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/* need to setup ddc on the bridge */
|
||||
if (radeon_connector_encoder_is_dp_bridge(connector)) {
|
||||
if (encoder)
|
||||
radeon_atom_ext_encoder_setup_ddc(encoder);
|
||||
}
|
||||
ret = radeon_ddc_get_modes(radeon_connector);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1187,14 +1202,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
|
||||
if (radeon_connector->edid) {
|
||||
kfree(radeon_connector->edid);
|
||||
radeon_connector->edid = NULL;
|
||||
}
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||
if (encoder) {
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
|
||||
@ -1214,6 +1230,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||
atombios_set_edp_panel_power(connector,
|
||||
ATOM_TRANSMITTER_ACTION_POWER_OFF);
|
||||
} else {
|
||||
/* need to setup ddc on the bridge */
|
||||
if (radeon_connector_encoder_is_dp_bridge(connector)) {
|
||||
if (encoder)
|
||||
radeon_atom_ext_encoder_setup_ddc(encoder);
|
||||
}
|
||||
radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
|
||||
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
|
||||
ret = connector_status_connected;
|
||||
@ -1228,6 +1249,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
||||
ret = connector_status_connected;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == connector_status_disconnected) &&
|
||||
radeon_connector->dac_load_detect) {
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
struct drm_encoder_helper_funcs *encoder_funcs;
|
||||
if (encoder) {
|
||||
encoder_funcs = encoder->helper_private;
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radeon_connector_update_scratch_regs(connector, ret);
|
||||
@ -1242,7 +1273,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
|
||||
|
||||
/* XXX check mode bandwidth */
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
|
||||
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
|
||||
|
||||
if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
|
||||
@ -1252,7 +1284,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
|
||||
|
||||
/* AVIVO hardware supports downscaling modes larger than the panel
|
||||
/* AVIVO hardware supports downscaling modes larger than the panel
|
||||
* to the panel size, but I'm not sure this is desirable.
|
||||
*/
|
||||
if ((mode->hdisplay > native_mode->hdisplay) ||
|
||||
@ -1401,6 +1433,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
default:
|
||||
connector->interlace_allowed = true;
|
||||
connector->doublescan_allowed = true;
|
||||
radeon_connector->dac_load_detect = true;
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
@ -1422,6 +1458,12 @@ radeon_add_atom_connector(struct drm_device *dev,
|
||||
connector->doublescan_allowed = true;
|
||||
else
|
||||
connector->doublescan_allowed = false;
|
||||
if (connector_type == DRM_MODE_CONNECTOR_DVII) {
|
||||
radeon_connector->dac_load_detect = true;
|
||||
drm_connector_attach_property(&radeon_connector->base,
|
||||
rdev->mode_info.load_detect_property,
|
||||
1);
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
|
@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* clear wb memory */
|
||||
memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE);
|
||||
/* disable event_write fences */
|
||||
rdev->wb.use_event = false;
|
||||
/* disabled via module param */
|
||||
|
@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
|
||||
}
|
||||
|
||||
if (ASIC_IS_DCE3(rdev) &&
|
||||
(radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
|
||||
((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
|
||||
radeon_encoder_is_dp_bridge(encoder))) {
|
||||
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
|
||||
radeon_dp_set_link_config(connector, mode);
|
||||
}
|
||||
@ -660,21 +661,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
|
||||
if (radeon_encoder_is_dp_bridge(encoder))
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
|
||||
/* DVO is always DVO */
|
||||
if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
|
||||
return ATOM_ENCODER_MODE_DVO;
|
||||
|
||||
connector = radeon_get_connector_for_encoder(encoder);
|
||||
if (!connector) {
|
||||
switch (radeon_encoder->encoder_id) {
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
|
||||
return ATOM_ENCODER_MODE_DVI;
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
|
||||
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
|
||||
default:
|
||||
return ATOM_ENCODER_MODE_CRT;
|
||||
}
|
||||
}
|
||||
/* if we don't have an active device yet, just use one of
|
||||
* the connectors tied to the encoder.
|
||||
*/
|
||||
if (!connector)
|
||||
connector = radeon_get_connector_for_encoder_init(encoder);
|
||||
radeon_connector = to_radeon_connector(connector);
|
||||
|
||||
switch (connector->connector_type) {
|
||||
@ -1526,26 +1522,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
}
|
||||
|
||||
if (ext_encoder) {
|
||||
int action;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
default:
|
||||
if (ASIC_IS_DCE41(rdev))
|
||||
action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
|
||||
else
|
||||
action = ATOM_ENABLE;
|
||||
if (ASIC_IS_DCE41(rdev)) {
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
|
||||
} else
|
||||
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
if (ASIC_IS_DCE41(rdev))
|
||||
action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
|
||||
else
|
||||
action = ATOM_DISABLE;
|
||||
if (ASIC_IS_DCE41(rdev)) {
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
|
||||
} else
|
||||
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
|
||||
break;
|
||||
}
|
||||
atombios_external_encoder_setup(encoder, ext_encoder, action);
|
||||
}
|
||||
|
||||
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
|
||||
@ -2004,6 +2003,65 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
|
||||
struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
|
||||
u32 bios_0_scratch;
|
||||
|
||||
if (!ASIC_IS_DCE4(rdev))
|
||||
return connector_status_unknown;
|
||||
|
||||
if (!ext_encoder)
|
||||
return connector_status_unknown;
|
||||
|
||||
if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
|
||||
return connector_status_unknown;
|
||||
|
||||
/* load detect on the dp bridge */
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
|
||||
|
||||
bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
|
||||
|
||||
DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
|
||||
if (bios_0_scratch & ATOM_S0_CRT1_MASK)
|
||||
return connector_status_connected;
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
|
||||
if (bios_0_scratch & ATOM_S0_CRT2_MASK)
|
||||
return connector_status_connected;
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
|
||||
if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
|
||||
return connector_status_connected;
|
||||
}
|
||||
if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
|
||||
if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
|
||||
return connector_status_connected; /* CTV */
|
||||
else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
|
||||
return connector_status_connected; /* STV */
|
||||
}
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
void
|
||||
radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
|
||||
|
||||
if (ext_encoder)
|
||||
/* ddc_setup on the dp bridge */
|
||||
atombios_external_encoder_setup(encoder, ext_encoder,
|
||||
EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
|
||||
|
||||
}
|
||||
|
||||
static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
@ -2167,7 +2225,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
|
||||
.mode_set = radeon_atom_encoder_mode_set,
|
||||
.commit = radeon_atom_encoder_commit,
|
||||
.disable = radeon_atom_encoder_disable,
|
||||
/* no detect for TMDS/LVDS yet */
|
||||
.detect = radeon_atom_dig_detect,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
|
||||
|
@ -40,6 +40,35 @@
|
||||
#include "radeon.h"
|
||||
#include "radeon_trace.h"
|
||||
|
||||
static void radeon_fence_write(struct radeon_device *rdev, u32 seq)
|
||||
{
|
||||
if (rdev->wb.enabled) {
|
||||
u32 scratch_index;
|
||||
if (rdev->wb.use_event)
|
||||
scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
else
|
||||
scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
|
||||
} else
|
||||
WREG32(rdev->fence_drv.scratch_reg, seq);
|
||||
}
|
||||
|
||||
static u32 radeon_fence_read(struct radeon_device *rdev)
|
||||
{
|
||||
u32 seq;
|
||||
|
||||
if (rdev->wb.enabled) {
|
||||
u32 scratch_index;
|
||||
if (rdev->wb.use_event)
|
||||
scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
else
|
||||
scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
|
||||
} else
|
||||
seq = RREG32(rdev->fence_drv.scratch_reg);
|
||||
return seq;
|
||||
}
|
||||
|
||||
int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
|
||||
return 0;
|
||||
}
|
||||
fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
|
||||
if (!rdev->cp.ready) {
|
||||
if (!rdev->cp.ready)
|
||||
/* FIXME: cp is not running assume everythings is done right
|
||||
* away
|
||||
*/
|
||||
WREG32(rdev->fence_drv.scratch_reg, fence->seq);
|
||||
} else
|
||||
radeon_fence_write(rdev, fence->seq);
|
||||
else
|
||||
radeon_fence_ring_emit(rdev, fence);
|
||||
|
||||
trace_radeon_fence_emit(rdev->ddev, fence->seq);
|
||||
@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev)
|
||||
bool wake = false;
|
||||
unsigned long cjiffies;
|
||||
|
||||
if (rdev->wb.enabled) {
|
||||
u32 scratch_index;
|
||||
if (rdev->wb.use_event)
|
||||
scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
else
|
||||
scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
|
||||
seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
|
||||
} else
|
||||
seq = RREG32(rdev->fence_drv.scratch_reg);
|
||||
seq = radeon_fence_read(rdev);
|
||||
if (seq != rdev->fence_drv.last_seq) {
|
||||
rdev->fence_drv.last_seq = seq;
|
||||
rdev->fence_drv.last_jiffies = jiffies;
|
||||
@ -251,7 +272,7 @@ retry:
|
||||
r = radeon_gpu_reset(rdev);
|
||||
if (r)
|
||||
return r;
|
||||
WREG32(rdev->fence_drv.scratch_reg, fence->seq);
|
||||
radeon_fence_write(rdev, fence->seq);
|
||||
rdev->gpu_lockup = false;
|
||||
}
|
||||
timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
|
||||
@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
|
||||
write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
|
||||
return r;
|
||||
}
|
||||
WREG32(rdev->fence_drv.scratch_reg, 0);
|
||||
radeon_fence_write(rdev, 0);
|
||||
atomic_set(&rdev->fence_drv.seq, 0);
|
||||
INIT_LIST_HEAD(&rdev->fence_drv.created);
|
||||
INIT_LIST_HEAD(&rdev->fence_drv.emited);
|
||||
@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
|
||||
struct radeon_fence *fence;
|
||||
|
||||
seq_printf(m, "Last signaled fence 0x%08X\n",
|
||||
RREG32(rdev->fence_drv.scratch_reg));
|
||||
radeon_fence_read(rdev));
|
||||
if (!list_empty(&rdev->fence_drv.emited)) {
|
||||
fence = list_entry(rdev->fence_drv.emited.prev,
|
||||
struct radeon_fence, list);
|
||||
|
@ -483,6 +483,8 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev);
|
||||
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
|
||||
int action, uint8_t lane_num,
|
||||
uint8_t lane_set);
|
||||
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 int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
|
||||
u8 write_byte, u8 *read_byte);
|
||||
|
||||
|
@ -520,6 +520,8 @@ struct drm_connector {
|
||||
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
||||
uint32_t force_encoder_id;
|
||||
struct drm_encoder *encoder; /* currently active encoder */
|
||||
|
||||
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user