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

Commit 930b9d94 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-linus

* 'nouveau/for-airlied' of ../drm-nouveau-next: (21 commits)
  drm/nouveau: bail out of auxch transaction if we repeatedly recieve defers
  drm/nv50: implement gpio set/get routines
  drm/nv50: parse/use some more de-magiced parts of gpio table entries
  drm/nouveau: store raw gpio table entry in bios gpio structs
  drm/nv40: Init some tiling-related PGRAPH state.
  drm/nv50: Add NVA3 support in ctxprog/ctxvals generator.
  drm/nv50: another dodgy DP hack
  drm/nv50: punt hotplug irq handling out to workqueue
  drm/nv50: preserve an unknown SOR_MODECTRL value for DP encoders
  drm/nv50: Allow using the NVA3 new compute class.
  drm/nv50: cleanup properly if PDISPLAY init fails
  drm/nouveau: fixup the init failure paths some more
  drm/nv50: fix instmem init on IGPs if stolen mem crosses 4GiB mark
  drm/nv40: add LVDS table quirk for Dell Latitude D620
  drm/nv40: rework lvds table parsing
  drm/nouveau: detect vram amount once, and save the value
  drm/nouveau: remove some unused members from drm_nouveau_private
  drm/nouveau: Make use of TTM busy_placements.
  drm/nv50: add more 0x100c80 flushy magic
  drm/nv50: fix fbcon when framebuffer above 4GiB mark
  ...
parents 3a89b4a9 8e024f13
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
             nv50_cursor.o nv50_display.o nv50_fbcon.o \
             nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
             nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
             nv17_gpio.o
             nv17_gpio.o nv50_gpio.o

nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+59 −68
Original line number Diff line number Diff line
@@ -2573,48 +2573,34 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
	 * each GPIO according to various values listed in each entry
	 */

	const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
	struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
	const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
	const uint8_t *gpio_table = &bios->data[bios->dcb.gpio_table_ptr];
	const uint8_t *gpio_entry;
	int i;

	if (!iexec->execute)
		return 1;

	if (bios->dcb.version != 0x40) {
		NV_ERROR(bios->dev, "DCB table not version 4.0\n");
		return 0;
	}

	if (!bios->dcb.gpio_table_ptr) {
		NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
		return 0;
	if (dev_priv->card_type != NV_50) {
		NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
		return -ENODEV;
	}

	gpio_entry = gpio_table + gpio_table[1];
	for (i = 0; i < gpio_table[2]; i++, gpio_entry += gpio_table[3]) {
		uint32_t entry = ROM32(gpio_entry[0]), r, s, v;
		int line = (entry & 0x0000001f);
	if (!iexec->execute)
		return 1;

		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, entry);
	for (i = 0; i < bios->dcb.gpio.entries; i++) {
		struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i];
		uint32_t r, s, v;

		if ((entry & 0x0000ff00) == 0x0000ff00)
			continue;
		BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry);

		r = nv50_gpio_reg[line >> 3];
		s = (line & 0x07) << 2;
		v = bios_rd32(bios, r) & ~(0x00000003 << s);
		if (entry & 0x01000000)
			v |= (((entry & 0x60000000) >> 29) ^ 2) << s;
		else
			v |= (((entry & 0x18000000) >> 27) ^ 2) << s;
		bios_wr32(bios, r, v);
		nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);

		r = nv50_gpio_ctl[line >> 4];
		s = (line & 0x0f);
		/* The NVIDIA binary driver doesn't appear to actually do
		 * any of this, my VBIOS does however.
		 */
		/* Not a clue, needs de-magicing */
		r = nv50_gpio_ctl[gpio->line >> 4];
		s = (gpio->line & 0x0f);
		v = bios_rd32(bios, r) & ~(0x00010001 << s);
		switch ((entry & 0x06000000) >> 25) {
		switch ((gpio->entry & 0x06000000) >> 25) {
		case 1:
			v |= (0x00000001 << s);
			break;
@@ -3198,7 +3184,6 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
	struct nvbios *bios = &dev_priv->vbios;
	unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
	uint16_t scriptptr = 0, clktable;
	uint8_t clktableptr = 0;

	/*
	 * For now we assume version 3.0 table - g80 support will need some
@@ -3217,26 +3202,29 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
		scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
		break;
	case LVDS_RESET:
		clktable = bios->fp.lvdsmanufacturerpointer + 15;
		if (dcbent->or == 4)
			clktable += 8;

		if (dcbent->lvdsconf.use_straps_for_mode) {
			if (bios->fp.dual_link)
				clktableptr += 2;
			if (bios->fp.BITbit1)
				clktableptr++;
				clktable += 4;
			if (bios->fp.if_is_24bit)
				clktable += 2;
		} else {
			/* using EDID */
			uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
			int fallbackcmpval = (dcbent->or == 4) ? 4 : 1;
			int cmpval_24bit = (dcbent->or == 4) ? 4 : 1;

			if (bios->fp.dual_link) {
				clktableptr += 2;
				fallbackcmpval *= 2;
				clktable += 4;
				cmpval_24bit <<= 1;
			}
			if (fallbackcmpval & fallback)
				clktableptr++;

			if (bios->fp.strapless_is_24bit & cmpval_24bit)
				clktable += 2;
		}

		/* adding outputset * 8 may not be correct */
		clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]);
		clktable = ROM16(bios->data[clktable]);
		if (!clktable) {
			NV_ERROR(dev, "Pixel clock comparison table not found\n");
			return -ENOENT;
@@ -3638,37 +3626,40 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
		*if_is_24bit = bios->data[lvdsofs] & 16;
		break;
	case 0x30:
		/*
		 * My money would be on there being a 24 bit interface bit in
		 * this table, but I have no example of a laptop bios with a
		 * 24 bit panel to confirm that. Hence we shout loudly if any
		 * bit other than bit 0 is set (I've not even seen bit 1)
		 */
		if (bios->data[lvdsofs] > 1)
			NV_ERROR(dev,
				 "You have a very unusual laptop display; please report it\n");
	case 0x40:
		/*
		 * No sign of the "power off for reset" or "reset for panel
		 * on" bits, but it's safer to assume we should
		 */
		bios->fp.power_off_for_reset = true;
		bios->fp.reset_after_pclk_change = true;

		/*
		 * It's ok lvdsofs is wrong for nv4x edid case; dual_link is
		 * over-written, and BITbit1 isn't used
		 * over-written, and if_is_24bit isn't used
		 */
		bios->fp.dual_link = bios->data[lvdsofs] & 1;
		bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
		bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
		break;
	case 0x40:
		bios->fp.dual_link = bios->data[lvdsofs] & 1;
		bios->fp.if_is_24bit = bios->data[lvdsofs] & 2;
		bios->fp.strapless_is_24bit = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
		bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
		break;
	}

	/* Dell Latitude D620 reports a too-high value for the dual-link
	 * transition freq, causing us to program the panel incorrectly.
	 *
	 * It doesn't appear the VBIOS actually uses its transition freq
	 * (90000kHz), instead it uses the "Number of LVDS channels" field
	 * out of the panel ID structure (http://www.spwg.org/).
	 *
	 * For the moment, a quirk will do :)
	 */
	if ((dev->pdev->device == 0x01d7) &&
	    (dev->pdev->subsystem_vendor == 0x1028) &&
	    (dev->pdev->subsystem_device == 0x01c2)) {
		bios->fp.duallink_transition_clk = 80000;
	}

	/* set dual_link flag for EDID case */
	if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
		bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
@@ -5077,25 +5068,25 @@ parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset)
	gpio->tag = tag;
	gpio->line = line;
	gpio->invert = flags != 4;
	gpio->entry = ent;
}

static void
parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset)
{
	uint32_t entry = ROM32(bios->data[offset]);
	struct dcb_gpio_entry *gpio;
	uint32_t ent = ROM32(bios->data[offset]);
	uint8_t line = ent & 0x1f,
		tag = ent >> 8 & 0xff;

	if (tag == 0xff)
	if ((entry & 0x0000ff00) == 0x0000ff00)
		return;

	gpio = new_gpio_entry(bios);

	/* Currently unused, we may need more fields parsed at some
	 * point. */
	gpio->tag = tag;
	gpio->line = line;
	gpio->tag = (entry & 0x0000ff00) >> 8;
	gpio->line = (entry & 0x0000001f) >> 0;
	gpio->state_default = (entry & 0x01000000) >> 24;
	gpio->state[0] = (entry & 0x18000000) >> 27;
	gpio->state[1] = (entry & 0x60000000) >> 29;
	gpio->entry = entry;
}

static void
+3 −1
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ struct dcb_gpio_entry {
	enum dcb_gpio_tag tag;
	int line;
	bool invert;
	uint32_t entry;
	uint8_t state_default;
	uint8_t state[2];
};

struct dcb_gpio_table {
@@ -267,7 +270,6 @@ struct nvbios {
		bool reset_after_pclk_change;
		bool dual_link;
		bool link_c_increment;
		bool BITbit1;
		bool if_is_24bit;
		int duallink_transition_clk;
		uint8_t strapless_is_24bit;
+36 −31
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ nouveau_bo_fixup_align(struct drm_device *dev,
	 * many small buffers.
	 */
	if (dev_priv->card_type == NV_50) {
		uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15;
		uint32_t block_size = dev_priv->vram_size >> 15;
		int i;

		switch (tile_flags) {
@@ -153,7 +153,7 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,

	nvbo->placement.fpfn = 0;
	nvbo->placement.lpfn = mappable ? dev_priv->fb_mappable_pages : 0;
	nouveau_bo_placement_set(nvbo, flags);
	nouveau_bo_placement_set(nvbo, flags, 0);

	nvbo->channel = chan;
	ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
@@ -172,26 +172,33 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
	return 0;
}

static void
set_placement_list(uint32_t *pl, unsigned *n, uint32_t type, uint32_t flags)
{
	*n = 0;

	if (type & TTM_PL_FLAG_VRAM)
		pl[(*n)++] = TTM_PL_FLAG_VRAM | flags;
	if (type & TTM_PL_FLAG_TT)
		pl[(*n)++] = TTM_PL_FLAG_TT | flags;
	if (type & TTM_PL_FLAG_SYSTEM)
		pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags;
}

void
nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t memtype)
nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy)
{
	int n = 0;
	struct ttm_placement *pl = &nvbo->placement;
	uint32_t flags = TTM_PL_MASK_CACHING |
		(nvbo->pin_refcnt ? TTM_PL_FLAG_NO_EVICT : 0);

	if (memtype & TTM_PL_FLAG_VRAM)
		nvbo->placements[n++] = TTM_PL_FLAG_VRAM | TTM_PL_MASK_CACHING;
	if (memtype & TTM_PL_FLAG_TT)
		nvbo->placements[n++] = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
	if (memtype & TTM_PL_FLAG_SYSTEM)
		nvbo->placements[n++] = TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
	nvbo->placement.placement = nvbo->placements;
	nvbo->placement.busy_placement = nvbo->placements;
	nvbo->placement.num_placement = n;
	nvbo->placement.num_busy_placement = n;
	pl->placement = nvbo->placements;
	set_placement_list(nvbo->placements, &pl->num_placement,
			   type, flags);

	if (nvbo->pin_refcnt) {
		while (n--)
			nvbo->placements[n] |= TTM_PL_FLAG_NO_EVICT;
	}
	pl->busy_placement = nvbo->busy_placements;
	set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
			   type | busy, flags);
}

int
@@ -199,7 +206,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
{
	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
	struct ttm_buffer_object *bo = &nvbo->bo;
	int ret, i;
	int ret;

	if (nvbo->pin_refcnt && !(memtype & (1 << bo->mem.mem_type))) {
		NV_ERROR(nouveau_bdev(bo->bdev)->dev,
@@ -215,9 +222,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype)
	if (ret)
		goto out;

	nouveau_bo_placement_set(nvbo, memtype);
	for (i = 0; i < nvbo->placement.num_placement; i++)
		nvbo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
	nouveau_bo_placement_set(nvbo, memtype, 0);

	ret = ttm_bo_validate(bo, &nvbo->placement, false, false);
	if (ret == 0) {
@@ -244,7 +249,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
{
	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
	struct ttm_buffer_object *bo = &nvbo->bo;
	int ret, i;
	int ret;

	if (--nvbo->pin_refcnt)
		return 0;
@@ -253,8 +258,7 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
	if (ret)
		return ret;

	for (i = 0; i < nvbo->placement.num_placement; i++)
		nvbo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
	nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);

	ret = ttm_bo_validate(bo, &nvbo->placement, false, false);
	if (ret == 0) {
@@ -395,8 +399,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
		man->io_addr = NULL;
		man->io_offset = drm_get_resource_start(dev, 1);
		man->io_size = drm_get_resource_len(dev, 1);
		if (man->io_size > nouveau_mem_fb_amount(dev))
			man->io_size = nouveau_mem_fb_amount(dev);
		if (man->io_size > dev_priv->vram_size)
			man->io_size = dev_priv->vram_size;

		man->gpu_offset = dev_priv->vm_vram_base;
		break;
@@ -439,10 +443,11 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)

	switch (bo->mem.mem_type) {
	case TTM_PL_VRAM:
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT);
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT,
					 TTM_PL_FLAG_SYSTEM);
		break;
	default:
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM);
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM, 0);
		break;
	}

+0 −2
Original line number Diff line number Diff line
@@ -142,7 +142,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
					   GFP_KERNEL);
	if (!dev_priv->fifos[channel])
		return -ENOMEM;
	dev_priv->fifo_alloc_count++;
	chan = dev_priv->fifos[channel];
	INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
	INIT_LIST_HEAD(&chan->fence.pending);
@@ -321,7 +320,6 @@ nouveau_channel_free(struct nouveau_channel *chan)
		iounmap(chan->user);

	dev_priv->fifos[chan->id] = NULL;
	dev_priv->fifo_alloc_count--;
	kfree(chan);
}

Loading