Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit abefedd5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (95 commits)
  drm/radeon/kms: preface warning printk with driver name
  drm/radeon/kms: drop unnecessary printks.
  drm: fix regression in fb blank handling
  drm/radeon/kms: make hibernate work on IGPs
  drm/vmwgfx: Optimize memory footprint for DMA buffers.
  drm/ttm: Allow system memory as a busy placement.
  drm/ttm: Fix race condition in ttm_bo_delayed_delete (v3, final)
  drm/nv50: prevent switching off SOR when in use for DVI-over-DP
  drm/nv50: fail auxch transaction if reply count not what we expect
  drm/nouveau: fix failure path if userspace specifies no valid memtypes
  drm/nouveau: report LVDS as disconnected if lid closed
  drm/radeon/kms: fix legacy get_engine/memory clock
  drm/radeon/kms/atom: atom parser fixes
  drm/radeon/kms: clean up atombios pll code
  drm/radeon/kms: clean up pll struct
  drm/radeon/kms/atom: fix crtc lock ordering
  drm/radeon: r6xx/r7xx possible security issue, system ram access
  drm/radeon/kms: r600/r700 don't test ib if ib initialization fails
  drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object
  drm/radeon/kms: r600 handle irq vector ring overflow
  ...
parents 840f51ff 7087e162
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -633,8 +633,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
		return NULL;
		return NULL;
	}
	}
	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
	if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
		printk(KERN_WARNING "integrated sync not supported\n");
		printk(KERN_WARNING "composite sync not supported\n");
		return NULL;
	}
	}


	/* it is incorrect if hsync/vsync width is zero */
	/* it is incorrect if hsync/vsync width is zero */
+1 −1
Original line number Original line Diff line number Diff line
@@ -389,7 +389,7 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)
		break;
		break;
	/* Display: Off; HSync: On, VSync: On */
	/* Display: Off; HSync: On, VSync: On */
	case FB_BLANK_NORMAL:
	case FB_BLANK_NORMAL:
		drm_fb_helper_off(info, DRM_MODE_DPMS_ON);
		drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY);
		break;
		break;
	/* Display: Off; HSync: Off, VSync: On */
	/* Display: Off; HSync: Off, VSync: On */
	case FB_BLANK_HSYNC_SUSPEND:
	case FB_BLANK_HSYNC_SUSPEND:
+80 −107
Original line number Original line Diff line number Diff line
@@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg)
	struct drm_device *dev = bios->dev;
	struct drm_device *dev = bios->dev;


	/* C51 has misaligned regs on purpose. Marvellous */
	/* C51 has misaligned regs on purpose. Marvellous */
	if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) {
	if (reg & 0x2 ||
		NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n",
	    (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
			 reg);
		NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
		return 0;

	}
	/* warn on C51 regs that haven't been verified accessible in tracing */
	/*
	 * Warn on C51 regs that have not been verified accessible in
	 * mmiotracing
	 */
	if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
	if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
	    reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
	    reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
		NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
		NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
			reg);
			reg);


	/* Trust the init scripts on G80 */
	if (reg >= (8*1024*1024)) {
	if (dev_priv->card_type >= NV_50)
		NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
		return 1;
		return 0;

	#define WITHIN(x, y, z) ((x >= y) && (x < y + z))
	if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE))
		return 1;
	if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE))
		return 1;
	if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE))
		return 1;
	if (dev_priv->VBIOS.pub.chip_version >= 0x30 &&
	    (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600))
		return 1;
	if (dev_priv->VBIOS.pub.chip_version >= 0x40 &&
						WITHIN(reg, 0xc000, 0x48))
		return 1;
	if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
		return 1;
	if (dev_priv->VBIOS.pub.chip_version >= 0x40) {
		if (reg == 0x00011014 || reg == 0x00020328)
			return 1;
		if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */
			return 1;
	}
	}
	if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE))
		return 1;
	if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE))
		return 1;
	if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2))
		return 1;
	if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2))
		return 1;
	if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
		return 1;
	if (dev_priv->VBIOS.pub.chip_version == 0x51 &&
				WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE))
		return 1;
	#undef WITHIN

	NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg);


	return 0;
	return 1;
}
}


static bool
static bool
@@ -3196,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
	}
	}
#ifdef __powerpc__
#ifdef __powerpc__
	/* Powerbook specific quirks */
	/* Powerbook specific quirks */
	if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329))
	if ((dev->pci_device & 0xffff) == 0x0179 ||
	    (dev->pci_device & 0xffff) == 0x0189 ||
	    (dev->pci_device & 0xffff) == 0x0329) {
		if (script == LVDS_RESET) {
			nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
			nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
	if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) {

		if (script == LVDS_PANEL_ON) {
		} else if (script == LVDS_PANEL_ON) {
			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
			bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
		}
				  | (1 << 31));
		if (script == LVDS_PANEL_OFF) {
			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
			bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);

		} else if (script == LVDS_PANEL_OFF) {
			bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
				  bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
				  & ~(1 << 31));
			bios_wr32(bios, NV_PCRTC_GPIO_EXT,
				  bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
		}
		}
	}
	}
#endif
#endif
@@ -5434,52 +5402,49 @@ static bool
parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
		  uint32_t conn, uint32_t conf, struct dcb_entry *entry)
{
{
	if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 &&
	switch (conn & 0x0000000f) {
	    conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 &&
	case 0:
	    conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 &&
		entry->type = OUTPUT_ANALOG;
	    conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
		break;
	    conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 &&
	case 1:
	    conn != 0xf2205004 && conn != 0xf2209004) {
		entry->type = OUTPUT_TV;
		NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n");
		break;

	case 2:
		/* cause output setting to fail for !TV, so message is seen */
	case 3:
		if ((conn & 0xf) != 0x1)
			dcb->entries = 0;

		return false;
	}
	/* most of the below is a "best guess" atm */
	entry->type = conn & 0xf;
	if (entry->type == 2)
		/* another way of specifying straps based lvds... */
		entry->type = OUTPUT_LVDS;
	if (entry->type == 4) { /* digital */
		if (conn & 0x10)
		entry->type = OUTPUT_LVDS;
		entry->type = OUTPUT_LVDS;
		else
		break;
	case 4:
		switch ((conn & 0x000000f0) >> 4) {
		case 0:
			entry->type = OUTPUT_TMDS;
			entry->type = OUTPUT_TMDS;
			break;
		case 1:
			entry->type = OUTPUT_LVDS;
			break;
		default:
			NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
				 (conn & 0x000000f0) >> 4);
			return false;
		}
		break;
	default:
		NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
		return false;
	}
	}
	/* what's in bits 5-13? could be some encoder maker thing, in tv case */

	entry->i2c_index = (conn >> 14) & 0xf;
	entry->i2c_index = (conn & 0x0003c000) >> 14;
	/* raw heads field is in range 0-1, so move to 1-2 */
	entry->heads = ((conn & 0x001c0000) >> 18) + 1;
	entry->heads = ((conn >> 18) & 0x7) + 1;
	entry->or = entry->heads; /* same as heads, hopefully safe enough */
	entry->location = (conn >> 21) & 0xf;
	entry->location = (conn & 0x01e00000) >> 21;
	/* unused: entry->bus = (conn >> 25) & 0x7; */
	entry->bus = (conn & 0x0e000000) >> 25;
	/* set or to be same as heads -- hopefully safe enough */
	entry->or = entry->heads;
	entry->duallink_possible = false;
	entry->duallink_possible = false;


	switch (entry->type) {
	switch (entry->type) {
	case OUTPUT_ANALOG:
	case OUTPUT_ANALOG:
		entry->crtconf.maxfreq = (conf & 0xffff) * 10;
		entry->crtconf.maxfreq = (conf & 0xffff) * 10;
		break;
		break;
	case OUTPUT_LVDS:
	case OUTPUT_TV:
		/*
		entry->tvconf.has_component_output = false;
		 * This is probably buried in conn's unknown bits.
		 * This will upset EDID-ful models, if they exist
		 */
		entry->lvdsconf.use_straps_for_mode = true;
		entry->lvdsconf.use_power_scripts = true;
		break;
		break;
	case OUTPUT_TMDS:
	case OUTPUT_TMDS:
		/*
		/*
@@ -5488,8 +5453,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
		 */
		 */
		fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
		fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
		break;
		break;
	case OUTPUT_TV:
	case OUTPUT_LVDS:
		entry->tvconf.has_component_output = false;
		if ((conn & 0x00003f00) != 0x10)
			entry->lvdsconf.use_straps_for_mode = true;
		entry->lvdsconf.use_power_scripts = true;
		break;
	default:
		break;
		break;
	}
	}


@@ -5564,11 +5533,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
	dcb->entries = newentries;
	dcb->entries = newentries;
}
}


static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
static int
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
{
{
	struct drm_nouveau_private *dev_priv = dev->dev_private;
	struct bios_parsed_dcb *bdcb = &bios->bdcb;
	struct bios_parsed_dcb *bdcb = &bios->bdcb;
	struct parsed_dcb *dcb;
	struct parsed_dcb *dcb;
	uint16_t dcbptr, i2ctabptr = 0;
	uint16_t dcbptr = 0, i2ctabptr = 0;
	uint8_t *dcbtable;
	uint8_t *dcbtable;
	uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
	uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
	bool configblock = true;
	bool configblock = true;
@@ -5579,16 +5550,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two
	dcb->entries = 0;
	dcb->entries = 0;


	/* get the offset from 0x36 */
	/* get the offset from 0x36 */
	if (dev_priv->card_type > NV_04) {
		dcbptr = ROM16(bios->data[0x36]);
		dcbptr = ROM16(bios->data[0x36]);
		if (dcbptr == 0x0000)
			NV_WARN(dev, "No output data (DCB) found in BIOS\n");
	}


	if (dcbptr == 0x0) {
		NV_WARN(dev, "No output data (DCB) found in BIOS, "
			       "assuming a CRT output exists\n");
	/* this situation likely means a really old card, pre DCB */
	/* this situation likely means a really old card, pre DCB */
	if (dcbptr == 0x0) {
		NV_INFO(dev, "Assuming a CRT output exists\n");
		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
		fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);


		if (nv04_tv_identify(dev,
		if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
				     bios->legacy.i2c_indices.tv) >= 0)
			fabricate_tv_output(dcb, twoHeads);
			fabricate_tv_output(dcb, twoHeads);


		return 0;
		return 0;
+2 −0
Original line number Original line Diff line number Diff line
@@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,


	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
					evict, no_wait, new_mem);
					evict, no_wait, new_mem);
	if (nvbo->channel && nvbo->channel != chan)
		ret = nouveau_fence_wait(fence, NULL, false, false);
	nouveau_fence_unref((void *)&fence);
	nouveau_fence_unref((void *)&fence);
	return ret;
	return ret;
}
}
+26 −5
Original line number Original line Diff line number Diff line
@@ -24,9 +24,12 @@
 *
 *
 */
 */


#include <acpi/button.h>

#include "drmP.h"
#include "drmP.h"
#include "drm_edid.h"
#include "drm_edid.h"
#include "drm_crtc_helper.h"
#include "drm_crtc_helper.h"

#include "nouveau_reg.h"
#include "nouveau_reg.h"
#include "nouveau_drv.h"
#include "nouveau_drv.h"
#include "nouveau_encoder.h"
#include "nouveau_encoder.h"
@@ -83,14 +86,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
static void
static void
nouveau_connector_destroy(struct drm_connector *drm_connector)
nouveau_connector_destroy(struct drm_connector *drm_connector)
{
{
	struct nouveau_connector *connector = nouveau_connector(drm_connector);
	struct nouveau_connector *nv_connector =
	struct drm_device *dev = connector->base.dev;
		nouveau_connector(drm_connector);
	struct drm_device *dev = nv_connector->base.dev;


	NV_DEBUG_KMS(dev, "\n");
	NV_DEBUG_KMS(dev, "\n");


	if (!connector)
	if (!nv_connector)
		return;
		return;


	kfree(nv_connector->edid);
	drm_sysfs_connector_remove(drm_connector);
	drm_sysfs_connector_remove(drm_connector);
	drm_connector_cleanup(drm_connector);
	drm_connector_cleanup(drm_connector);
	kfree(drm_connector);
	kfree(drm_connector);
@@ -233,10 +238,21 @@ nouveau_connector_detect(struct drm_connector *connector)
	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
	if (nv_encoder && nv_connector->native_mode) {
	if (nv_encoder && nv_connector->native_mode) {
#ifdef CONFIG_ACPI
		if (!nouveau_ignorelid && !acpi_lid_open())
			return connector_status_disconnected;
#endif
		nouveau_connector_set_encoder(connector, nv_encoder);
		nouveau_connector_set_encoder(connector, nv_encoder);
		return connector_status_connected;
		return connector_status_connected;
	}
	}


	/* Cleanup the previous EDID block. */
	if (nv_connector->edid) {
		drm_mode_connector_update_edid_property(connector, NULL);
		kfree(nv_connector->edid);
		nv_connector->edid = NULL;
	}

	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
	if (i2c) {
	if (i2c) {
		nouveau_connector_ddc_prepare(connector, &flags);
		nouveau_connector_ddc_prepare(connector, &flags);
@@ -247,7 +263,7 @@ nouveau_connector_detect(struct drm_connector *connector)
		if (!nv_connector->edid) {
		if (!nv_connector->edid) {
			NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
			NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
				 drm_get_connector_name(connector));
				 drm_get_connector_name(connector));
			return connector_status_disconnected;
			goto detect_analog;
		}
		}


		if (nv_encoder->dcb->type == OUTPUT_DP &&
		if (nv_encoder->dcb->type == OUTPUT_DP &&
@@ -281,6 +297,7 @@ nouveau_connector_detect(struct drm_connector *connector)
		return connector_status_connected;
		return connector_status_connected;
	}
	}


detect_analog:
	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
	nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
	if (!nv_encoder)
	if (!nv_encoder)
		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
		nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
@@ -687,8 +704,12 @@ nouveau_connector_create_lvds(struct drm_device *dev,
	 */
	 */
	if (!nv_connector->edid && !nv_connector->native_mode &&
	if (!nv_connector->edid && !nv_connector->native_mode &&
	    !dev_priv->VBIOS.pub.fp_no_ddc) {
	    !dev_priv->VBIOS.pub.fp_no_ddc) {
		nv_connector->edid =
		struct edid *edid =
			(struct edid *)nouveau_bios_embedded_edid(dev);
			(struct edid *)nouveau_bios_embedded_edid(dev);
		if (edid) {
			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
			*(nv_connector->edid) = *edid;
		}
	}
	}


	if (!nv_connector->edid)
	if (!nv_connector->edid)
Loading