mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +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:
|
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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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) >>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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:
|
||||||
|
@ -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 */
|
||||||
|
@ -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 = {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user