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:
Linus Torvalds 2011-06-16 17:54:41 -07:00
commit eb96c92515
15 changed files with 237 additions and 75 deletions

View File

@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)
bad: bad:
if (raw_edid) { 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); print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
printk("\n"); printk(KERN_ERR "\n");
} }
return 0; return 0;
} }
@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
return ret == 2 ? 0 : -1; 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 * static u8 *
drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) 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; goto out;
if (drm_edid_block_valid(block)) if (drm_edid_block_valid(block))
break; break;
if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
connector->null_edid_counter++;
goto carp;
}
} }
if (i == 4) if (i == 4)
goto carp; goto carp;

View File

@ -28,6 +28,7 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/ratelimit.h>
#include "drmP.h" #include "drmP.h"
#include "drm_core.h" #include "drm_core.h"
@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
return -EFAULT; return -EFAULT;
m32.handle = (unsigned long)handle; m32.handle = (unsigned long)handle;
if (m32.handle != (unsigned long)handle && printk_ratelimit()) if (m32.handle != (unsigned long)handle)
printk(KERN_ERR "compat_drm_addmap truncated handle" printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
" %p for type %d offset %x\n", " %p for type %d offset %x\n",
handle, m32.type, m32.offset); handle, m32.type, m32.offset);
if (copy_to_user(argp, &m32, sizeof(m32))) if (copy_to_user(argp, &m32, sizeof(m32)))
return -EFAULT; return -EFAULT;

View File

@ -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) || if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
(p->busnum & 0xff) != dev->pdev->bus->number || (p->busnum & 0xff) != dev->pdev->bus->number ||
@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {
.get_name = drm_pci_get_name, .get_name = drm_pci_get_name,
.set_busid = drm_pci_set_busid, .set_busid = drm_pci_set_busid,
.set_unique = drm_pci_set_unique, .set_unique = drm_pci_set_unique,
.irq_by_busid = drm_pci_irq_by_busid,
.agp_init = drm_pci_agp_init, .agp_init = drm_pci_agp_init,
}; };

View File

@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)
bus->reg0 = i | GMBUS_RATE_100KHZ; bus->reg0 = i | GMBUS_RATE_100KHZ;
/* XXX force bit banging until GMBUS is fully debugged */ /* 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); intel_i2c_reset(dev_priv->dev);

View File

@ -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_OFF 0x10
#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11
#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12
#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP 0x14
// ucConfig // ucConfig
#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03

View File

@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
DISPPLL_CONFIG_DUAL_LINK; 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, atom_execute_table(rdev->mode_info.atom_context,
index, (uint32_t *)&args); index, (uint32_t *)&args);
adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;

View File

@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
/* get temperature in millidegrees */ /* get temperature in millidegrees */
int evergreen_get_temp(struct radeon_device *rdev) 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) { if (rdev->family == CHIP_JUNIPER) {
toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>

View File

@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = {
int radeon_asic_init(struct radeon_device *rdev) int radeon_asic_init(struct radeon_device *rdev)
{ {
radeon_register_accessor_init(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) { switch (rdev->family) {
case CHIP_R100: case CHIP_R100:
case CHIP_RV100: case CHIP_RV100:
@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev)
case CHIP_JUNIPER: case CHIP_JUNIPER:
case CHIP_CYPRESS: case CHIP_CYPRESS:
case CHIP_HEMLOCK: case CHIP_HEMLOCK:
/* set num crtcs */
if (rdev->family == CHIP_CEDAR)
rdev->num_crtc = 4;
else
rdev->num_crtc = 6;
rdev->asic = &evergreen_asic; rdev->asic = &evergreen_asic;
break; break;
case CHIP_PALM: case CHIP_PALM:
@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev)
case CHIP_BARTS: case CHIP_BARTS:
case CHIP_TURKS: case CHIP_TURKS:
case CHIP_CAICOS: case CHIP_CAICOS:
/* set num crtcs */
if (rdev->family == CHIP_CAICOS)
rdev->num_crtc = 4;
else
rdev->num_crtc = 6;
rdev->asic = &btc_asic; rdev->asic = &btc_asic;
break; break;
case CHIP_CAYMAN: case CHIP_CAYMAN:
rdev->asic = &cayman_asic; rdev->asic = &cayman_asic;
/* set num crtcs */
rdev->num_crtc = 6;
break; break;
default: default:
/* FIXME: not supported yet */ /* FIXME: not supported yet */
@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev)
rdev->asic->set_memory_clock = NULL; 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; return 0;
} }

View File

@ -1553,9 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
(rdev->pdev->subsystem_device == 0x4a48)) { (rdev->pdev->subsystem_device == 0x4a48)) {
/* Mac X800 */ /* Mac X800 */
rdev->mode_info.connector_table = CT_MAC_X800; rdev->mode_info.connector_table = CT_MAC_X800;
} else if (of_machine_is_compatible("PowerMac7,2") || } else if ((of_machine_is_compatible("PowerMac7,2") ||
of_machine_is_compatible("PowerMac7,3")) { of_machine_is_compatible("PowerMac7,3")) &&
/* Mac G5 9600 */ (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; rdev->mode_info.connector_table = CT_MAC_G5_9600;
} else } else
#endif /* CONFIG_PPC_PMAC */ #endif /* CONFIG_PPC_PMAC */

View File

@ -44,6 +44,8 @@ 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;
@ -836,6 +838,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if (!radeon_connector->edid) { if (!radeon_connector->edid) {
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
drm_get_connector_name(connector)); 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 { } else {
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); 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 *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
int ret; int ret;
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
struct drm_encoder *encoder; (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
struct drm_display_mode *mode; struct drm_display_mode *mode;
if (!radeon_dig_connector->edp_on) 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); ATOM_TRANSMITTER_ACTION_POWER_OFF);
if (ret > 0) { if (ret > 0) {
encoder = radeon_best_single_encoder(connector);
if (encoder) { if (encoder) {
radeon_fixup_lvds_native_mode(encoder, connector); radeon_fixup_lvds_native_mode(encoder, connector);
/* add scaled modes */ /* add scaled modes */
@ -1102,8 +1111,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
/* add scaled modes */ /* add scaled modes */
radeon_add_common_modes(encoder, connector); 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); ret = radeon_ddc_get_modes(radeon_connector);
}
return ret; return ret;
} }
@ -1187,14 +1202,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector *radeon_connector = to_radeon_connector(connector);
enum drm_connector_status ret = connector_status_disconnected; enum drm_connector_status ret = connector_status_disconnected;
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; 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) { if (radeon_connector->edid) {
kfree(radeon_connector->edid); kfree(radeon_connector->edid);
radeon_connector->edid = NULL; radeon_connector->edid = NULL;
} }
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
struct drm_encoder *encoder = radeon_best_single_encoder(connector); (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
if (encoder) { if (encoder) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 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, atombios_set_edp_panel_power(connector,
ATOM_TRANSMITTER_ACTION_POWER_OFF); ATOM_TRANSMITTER_ACTION_POWER_OFF);
} 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);
}
radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
ret = connector_status_connected; ret = connector_status_connected;
@ -1228,6 +1249,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
ret = connector_status_connected; 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); 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 */ /* 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); struct drm_encoder *encoder = radeon_best_single_encoder(connector);
if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) 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 radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_display_mode *native_mode = &radeon_encoder->native_mode; 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. * to the panel size, but I'm not sure this is desirable.
*/ */
if ((mode->hdisplay > native_mode->hdisplay) || if ((mode->hdisplay > native_mode->hdisplay) ||
@ -1401,6 +1433,10 @@ radeon_add_atom_connector(struct drm_device *dev,
default: default:
connector->interlace_allowed = true; connector->interlace_allowed = true;
connector->doublescan_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; break;
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
@ -1422,6 +1458,12 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->doublescan_allowed = true; connector->doublescan_allowed = true;
else else
connector->doublescan_allowed = false; 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; break;
case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_LVDS:
case DRM_MODE_CONNECTOR_eDP: case DRM_MODE_CONNECTOR_eDP:

View File

@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev)
return r; return r;
} }
/* clear wb memory */
memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE);
/* disable event_write fences */ /* disable event_write fences */
rdev->wb.use_event = false; rdev->wb.use_event = false;
/* disabled via module param */ /* disabled via module param */

View File

@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
} }
if (ASIC_IS_DCE3(rdev) && 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); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
radeon_dp_set_link_config(connector, mode); 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)) if (radeon_encoder_is_dp_bridge(encoder))
return ATOM_ENCODER_MODE_DP; 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); connector = radeon_get_connector_for_encoder(encoder);
if (!connector) { /* if we don't have an active device yet, just use one of
switch (radeon_encoder->encoder_id) { * the connectors tied to the encoder.
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: */
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: if (!connector)
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: connector = radeon_get_connector_for_encoder_init(encoder);
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;
}
}
radeon_connector = to_radeon_connector(connector); radeon_connector = to_radeon_connector(connector);
switch (connector->connector_type) { switch (connector->connector_type) {
@ -1526,26 +1522,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
} }
if (ext_encoder) { if (ext_encoder) {
int action;
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
default: default:
if (ASIC_IS_DCE41(rdev)) if (ASIC_IS_DCE41(rdev)) {
action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; atombios_external_encoder_setup(encoder, ext_encoder,
else EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
action = ATOM_ENABLE; 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; break;
case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
if (ASIC_IS_DCE41(rdev)) if (ASIC_IS_DCE41(rdev)) {
action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; atombios_external_encoder_setup(encoder, ext_encoder,
else EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
action = ATOM_DISABLE; atombios_external_encoder_setup(encoder, ext_encoder,
EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
} else
atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
break; break;
} }
atombios_external_encoder_setup(encoder, ext_encoder, action);
} }
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); 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; 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) static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
{ {
struct radeon_encoder *radeon_encoder = to_radeon_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, .mode_set = radeon_atom_encoder_mode_set,
.commit = radeon_atom_encoder_commit, .commit = radeon_atom_encoder_commit,
.disable = radeon_atom_encoder_disable, .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 = { static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {

View File

@ -40,6 +40,35 @@
#include "radeon.h" #include "radeon.h"
#include "radeon_trace.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) int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
{ {
unsigned long irq_flags; unsigned long irq_flags;
@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
return 0; return 0;
} }
fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); 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 /* FIXME: cp is not running assume everythings is done right
* away * away
*/ */
WREG32(rdev->fence_drv.scratch_reg, fence->seq); radeon_fence_write(rdev, fence->seq);
} else else
radeon_fence_ring_emit(rdev, fence); radeon_fence_ring_emit(rdev, fence);
trace_radeon_fence_emit(rdev->ddev, fence->seq); 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; bool wake = false;
unsigned long cjiffies; unsigned long cjiffies;
if (rdev->wb.enabled) { seq = radeon_fence_read(rdev);
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);
if (seq != rdev->fence_drv.last_seq) { if (seq != rdev->fence_drv.last_seq) {
rdev->fence_drv.last_seq = seq; rdev->fence_drv.last_seq = seq;
rdev->fence_drv.last_jiffies = jiffies; rdev->fence_drv.last_jiffies = jiffies;
@ -251,7 +272,7 @@ retry:
r = radeon_gpu_reset(rdev); r = radeon_gpu_reset(rdev);
if (r) if (r)
return r; return r;
WREG32(rdev->fence_drv.scratch_reg, fence->seq); radeon_fence_write(rdev, fence->seq);
rdev->gpu_lockup = false; rdev->gpu_lockup = false;
} }
timeout = RADEON_FENCE_JIFFIES_TIMEOUT; 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); write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
return r; return r;
} }
WREG32(rdev->fence_drv.scratch_reg, 0); radeon_fence_write(rdev, 0);
atomic_set(&rdev->fence_drv.seq, 0); atomic_set(&rdev->fence_drv.seq, 0);
INIT_LIST_HEAD(&rdev->fence_drv.created); INIT_LIST_HEAD(&rdev->fence_drv.created);
INIT_LIST_HEAD(&rdev->fence_drv.emited); 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; struct radeon_fence *fence;
seq_printf(m, "Last signaled fence 0x%08X\n", 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)) { if (!list_empty(&rdev->fence_drv.emited)) {
fence = list_entry(rdev->fence_drv.emited.prev, fence = list_entry(rdev->fence_drv.emited.prev,
struct radeon_fence, list); struct radeon_fence, list);

View File

@ -483,6 +483,8 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev);
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
int action, uint8_t lane_num, int action, uint8_t lane_num,
uint8_t lane_set); uint8_t lane_set);
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, 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);

View File

@ -520,6 +520,8 @@ struct drm_connector {
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
uint32_t force_encoder_id; uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */ struct drm_encoder *encoder; /* currently active encoder */
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
}; };
/** /**