diff options
33 files changed, 508 insertions, 298 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2cc6e87d849d..18f41d7061f0 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -85,6 +85,8 @@ static struct edid_quirk {  	/* Envision Peripherals, Inc. EN-7100e */  	{ "EPI", 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH }, +	/* Envision EN2028 */ +	{ "EPI", 8232, EDID_QUIRK_PREFER_LARGE_60 },  	/* Funai Electronics PM36B */  	{ "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 | diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 7f0d807a0d0d..453df3f6053f 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index b5a9336a2e88..abc382a9918b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 4f88e6924d27..c0d7b0a3ece0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 9042dd7fb058..957d17629840 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -72,7 +72,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) { @@ -154,7 +154,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, @@ -173,26 +173,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; - -	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; - -	if (nvbo->pin_refcnt) { -		while (n--) -			nvbo->placements[n] |= TTM_PL_FLAG_NO_EVICT; -	} +	struct ttm_placement *pl = &nvbo->placement; +	uint32_t flags = TTM_PL_MASK_CACHING | +		(nvbo->pin_refcnt ? TTM_PL_FLAG_NO_EVICT : 0); + +	pl->placement = nvbo->placements; +	set_placement_list(nvbo->placements, &pl->num_placement, +			   type, flags); + +	pl->busy_placement = nvbo->busy_placements; +	set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, +			   type | busy, flags);  }  int @@ -200,7 +207,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, @@ -216,9 +223,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) { @@ -245,7 +250,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; @@ -254,8 +259,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) { @@ -396,8 +400,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; @@ -440,10 +444,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;  	} diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c index 6dfb425cbae9..1fc57ef58295 100644 --- a/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -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);  } diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 8ff9ef5d4b47..a251886a0ce6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -137,10 +137,9 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data)  {  	struct drm_info_node *node = (struct drm_info_node *) m->private;  	struct drm_minor *minor = node->minor; -	struct drm_device *dev = minor->dev; +	struct drm_nouveau_private *dev_priv = minor->dev->dev_private; -	seq_printf(m, "VRAM total: %dKiB\n", -		   (int)(nouveau_mem_fb_amount(dev) >> 10)); +	seq_printf(m, "VRAM total: %dKiB\n", (int)(dev_priv->vram_size >> 10));  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index f954ad93e81f..deeb21c6865c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -483,7 +483,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,  	ctrl |= (cmd << NV50_AUXCH_CTRL_CMD_SHIFT);  	ctrl |= ((data_nr - 1) << NV50_AUXCH_CTRL_LEN_SHIFT); -	for (;;) { +	for (i = 0; i < 16; i++) {  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x80000000);  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl);  		nv_wr32(dev, NV50_AUXCH_CTRL(index), ctrl | 0x00010000); @@ -502,6 +502,12 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,  			break;  	} +	if (i == 16) { +		NV_ERROR(dev, "auxch DEFER too many times, bailing\n"); +		ret = -EREMOTEIO; +		goto out; +	} +  	if (cmd & 1) {  		if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {  			ret = -EREMOTEIO; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d8b559011777..ace630aa89e1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -76,6 +76,7 @@ struct nouveau_bo {  	struct ttm_buffer_object bo;  	struct ttm_placement placement;  	u32 placements[3]; +	u32 busy_placements[3];  	struct ttm_bo_kmap_obj kmap;  	struct list_head head; @@ -519,6 +520,7 @@ struct drm_nouveau_private {  	struct workqueue_struct *wq;  	struct work_struct irq_work; +	struct work_struct hpd_work;  	struct list_head vbl_waiting; @@ -533,7 +535,6 @@ struct drm_nouveau_private {  	struct fb_info *fbdev_info; -	int fifo_alloc_count;  	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];  	struct nouveau_engine engine; @@ -553,12 +554,6 @@ struct drm_nouveau_private {  	uint32_t ramro_offset;  	uint32_t ramro_size; -	/* base physical addresses */ -	uint64_t fb_phys; -	uint64_t fb_available_size; -	uint64_t fb_mappable_pages; -	uint64_t fb_aper_free; -  	struct {  		enum {  			NOUVEAU_GART_NONE = 0, @@ -572,10 +567,6 @@ struct drm_nouveau_private {  		struct nouveau_gpuobj *sg_ctxdma;  		struct page *sg_dummy_page;  		dma_addr_t sg_dummy_bus; - -		/* nottm hack */ -		struct drm_ttm_backend *sg_be; -		unsigned long sg_handle;  	} gart_info;  	/* nv10-nv40 tiling regions */ @@ -584,6 +575,16 @@ struct drm_nouveau_private {  		spinlock_t lock;  	} tile; +	/* VRAM/fb configuration */ +	uint64_t vram_size; +	uint64_t vram_sys_base; + +	uint64_t fb_phys; +	uint64_t fb_available_size; +	uint64_t fb_mappable_pages; +	uint64_t fb_aper_free; +	int fb_mtrr; +  	/* G8x/G9x virtual address space */  	uint64_t vm_gart_base;  	uint64_t vm_gart_size; @@ -592,10 +593,6 @@ struct drm_nouveau_private {  	uint64_t vm_end;  	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];  	int vm_vram_pt_nr; -	uint64_t vram_sys_base; - -	/* the mtrr covering the FB */ -	int fb_mtrr;  	struct mem_block *ramin_heap; @@ -614,11 +611,7 @@ struct drm_nouveau_private {  	uint32_t dac_users[4];  	struct nouveau_suspend_resume { -		uint32_t fifo_mode; -		uint32_t graph_ctx_control; -		uint32_t graph_state;  		uint32_t *ramin_copy; -		uint64_t ramin_size;  	} susres;  	struct backlight_device *backlight; @@ -717,7 +710,7 @@ extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,  						 struct drm_file *, int tail);  extern void nouveau_mem_takedown(struct mem_block **heap);  extern void nouveau_mem_free_block(struct mem_block *); -extern uint64_t nouveau_mem_fb_amount(struct drm_device *); +extern int  nouveau_mem_detect(struct drm_device *dev);  extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);  extern int  nouveau_mem_init(struct drm_device *);  extern int  nouveau_mem_init_agp(struct drm_device *); @@ -1124,7 +1117,8 @@ extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);  extern int nouveau_bo_unpin(struct nouveau_bo *);  extern int nouveau_bo_map(struct nouveau_bo *);  extern void nouveau_bo_unmap(struct nouveau_bo *); -extern void nouveau_bo_placement_set(struct nouveau_bo *, uint32_t memtype); +extern void nouveau_bo_placement_set(struct nouveau_bo *, uint32_t type, +				     uint32_t busy);  extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index);  extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val);  extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); @@ -1168,6 +1162,10 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *,  int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);  int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +/* nv50_gpio.c */ +int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +  #ifndef ioread32_native  #ifdef __BIG_ENDIAN  #define ioread16_native ioread16be diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index bc4a24029ed1..9f28b94e479b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -47,6 +47,7 @@ struct nouveau_encoder {  	union {  		struct { +			int mc_unknown;  			int dpcd_version;  			int link_nr;  			int link_bw; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 0d22f66f1c79..1bc0b38a5167 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -180,40 +180,35 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,  {  	struct nouveau_bo *nvbo = gem->driver_private;  	struct ttm_buffer_object *bo = &nvbo->bo; -	uint64_t flags; +	uint32_t domains = valid_domains & +		(write_domains ? write_domains : read_domains); +	uint32_t pref_flags = 0, valid_flags = 0; -	if (!valid_domains || (!read_domains && !write_domains)) +	if (!domains)  		return -EINVAL; -	if (write_domains) { -		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && -		    (write_domains & NOUVEAU_GEM_DOMAIN_VRAM)) -			flags = TTM_PL_FLAG_VRAM; -		else -		if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) && -		    (write_domains & NOUVEAU_GEM_DOMAIN_GART)) -			flags = TTM_PL_FLAG_TT; -		else -			return -EINVAL; -	} else { -		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && -		    (read_domains & NOUVEAU_GEM_DOMAIN_VRAM) && -		    bo->mem.mem_type == TTM_PL_VRAM) -			flags = TTM_PL_FLAG_VRAM; -		else -		if ((valid_domains & NOUVEAU_GEM_DOMAIN_GART) && -		    (read_domains & NOUVEAU_GEM_DOMAIN_GART) && -		    bo->mem.mem_type == TTM_PL_TT) -			flags = TTM_PL_FLAG_TT; -		else -		if ((valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && -		    (read_domains & NOUVEAU_GEM_DOMAIN_VRAM)) -			flags = TTM_PL_FLAG_VRAM; -		else -			flags = TTM_PL_FLAG_TT; -	} +	if (valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) +		valid_flags |= TTM_PL_FLAG_VRAM; + +	if (valid_domains & NOUVEAU_GEM_DOMAIN_GART) +		valid_flags |= TTM_PL_FLAG_TT; + +	if ((domains & NOUVEAU_GEM_DOMAIN_VRAM) && +	    bo->mem.mem_type == TTM_PL_VRAM) +		pref_flags |= TTM_PL_FLAG_VRAM; + +	else if ((domains & NOUVEAU_GEM_DOMAIN_GART) && +		 bo->mem.mem_type == TTM_PL_TT) +		pref_flags |= TTM_PL_FLAG_TT; + +	else if (domains & NOUVEAU_GEM_DOMAIN_VRAM) +		pref_flags |= TTM_PL_FLAG_VRAM; + +	else +		pref_flags |= TTM_PL_FLAG_TT; + +	nouveau_bo_placement_set(nvbo, pref_flags, valid_flags); -	nouveau_bo_placement_set(nvbo, flags);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 2bd59a92fee5..13e73cee4c44 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -51,6 +51,7 @@ nouveau_irq_preinstall(struct drm_device *dev)  	if (dev_priv->card_type == NV_50) {  		INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); +		INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);  		INIT_LIST_HEAD(&dev_priv->vbl_waiting);  	}  } diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 2dc09dbd817d..775a7017af64 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -347,6 +347,20 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,  		return -EBUSY;  	} +	nv_wr32(dev, 0x100c80, 0x00040001); +	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); +		return -EBUSY; +	} + +	nv_wr32(dev, 0x100c80, 0x00060001); +	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); +		return -EBUSY; +	} +  	return 0;  } @@ -387,6 +401,20 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)  	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {  		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");  		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); +		return; +	} + +	nv_wr32(dev, 0x100c80, 0x00040001); +	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80)); +		return; +	} + +	nv_wr32(dev, 0x100c80, 0x00060001); +	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));  	}  } @@ -449,9 +477,30 @@ void nouveau_mem_close(struct drm_device *dev)  	}  } -/*XXX won't work on BSD because of pci_read_config_dword */  static uint32_t -nouveau_mem_fb_amount_igp(struct drm_device *dev) +nouveau_mem_detect_nv04(struct drm_device *dev) +{ +	uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0); + +	if (boot0 & 0x00000100) +		return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; + +	switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { +	case NV04_BOOT_0_RAM_AMOUNT_32MB: +		return 32 * 1024 * 1024; +	case NV04_BOOT_0_RAM_AMOUNT_16MB: +		return 16 * 1024 * 1024; +	case NV04_BOOT_0_RAM_AMOUNT_8MB: +		return 8 * 1024 * 1024; +	case NV04_BOOT_0_RAM_AMOUNT_4MB: +		return 4 * 1024 * 1024; +	} + +	return 0; +} + +static uint32_t +nouveau_mem_detect_nforce(struct drm_device *dev)  {  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct pci_dev *bridge; @@ -463,11 +512,11 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)  		return 0;  	} -	if (dev_priv->flags&NV_NFORCE) { +	if (dev_priv->flags & NV_NFORCE) {  		pci_read_config_dword(bridge, 0x7C, &mem);  		return (uint64_t)(((mem >> 6) & 31) + 1)*1024*1024;  	} else -	if (dev_priv->flags&NV_NFORCE2) { +	if (dev_priv->flags & NV_NFORCE2) {  		pci_read_config_dword(bridge, 0x84, &mem);  		return (uint64_t)(((mem >> 4) & 127) + 1)*1024*1024;  	} @@ -477,50 +526,32 @@ nouveau_mem_fb_amount_igp(struct drm_device *dev)  }  /* returns the amount of FB ram in bytes */ -uint64_t nouveau_mem_fb_amount(struct drm_device *dev) +int +nouveau_mem_detect(struct drm_device *dev)  {  	struct drm_nouveau_private *dev_priv = dev->dev_private; -	uint32_t boot0; - -	switch (dev_priv->card_type) { -	case NV_04: -		boot0 = nv_rd32(dev, NV03_BOOT_0); -		if (boot0 & 0x00000100) -			return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024; - -		switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) { -		case NV04_BOOT_0_RAM_AMOUNT_32MB: -			return 32 * 1024 * 1024; -		case NV04_BOOT_0_RAM_AMOUNT_16MB: -			return 16 * 1024 * 1024; -		case NV04_BOOT_0_RAM_AMOUNT_8MB: -			return 8 * 1024 * 1024; -		case NV04_BOOT_0_RAM_AMOUNT_4MB: -			return 4 * 1024 * 1024; -		} -		break; -	case NV_10: -	case NV_20: -	case NV_30: -	case NV_40: -	case NV_50: -	default: -		if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { -			return nouveau_mem_fb_amount_igp(dev); -		} else { -			uint64_t mem; -			mem = (nv_rd32(dev, NV04_FIFO_DATA) & -					NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK) >> -					NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT; -			return mem * 1024 * 1024; -		} -		break; + +	if (dev_priv->card_type == NV_04) { +		dev_priv->vram_size = nouveau_mem_detect_nv04(dev); +	} else +	if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) { +		dev_priv->vram_size = nouveau_mem_detect_nforce(dev); +	} else { +		dev_priv->vram_size  = nv_rd32(dev, NV04_FIFO_DATA); +		dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK; +		if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) +			dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12;  	} -	NV_ERROR(dev, -		"Unable to detect video ram size. Please report your setup to " -							DRIVER_EMAIL "\n"); -	return 0; +	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); +	if (dev_priv->vram_sys_base) { +		NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", +			dev_priv->vram_sys_base); +	} + +	if (dev_priv->vram_size) +		return 0; +	return -ENOMEM;  }  #if __OS_HAS_AGP @@ -631,15 +662,12 @@ nouveau_mem_init(struct drm_device *dev)  	spin_lock_init(&dev_priv->ttm.bo_list_lock);  	spin_lock_init(&dev_priv->tile.lock); -	dev_priv->fb_available_size = nouveau_mem_fb_amount(dev); - +	dev_priv->fb_available_size = dev_priv->vram_size;  	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;  	if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))  		dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);  	dev_priv->fb_mappable_pages >>= PAGE_SHIFT; -	NV_INFO(dev, "%d MiB VRAM\n", (int)(dev_priv->fb_available_size >> 20)); -  	/* remove reserved space at end of vram from available amount */  	dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram;  	dev_priv->fb_aper_free = dev_priv->fb_available_size; diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 86785b8d42ed..1d6ee8b55154 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -172,6 +172,24 @@ nouveau_sgdma_unbind(struct ttm_backend *be)  	}  	dev_priv->engine.instmem.finish_access(nvbe->dev); +	if (dev_priv->card_type == NV_50) { +		nv_wr32(dev, 0x100c80, 0x00050001); +		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +			NV_ERROR(dev, "0x100c80 = 0x%08x\n", +						nv_rd32(dev, 0x100c80)); +			return -EBUSY; +		} + +		nv_wr32(dev, 0x100c80, 0x00000001); +		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) { +			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n"); +			NV_ERROR(dev, "0x100c80 = 0x%08x\n", +						nv_rd32(dev, 0x100c80)); +			return -EBUSY; +		} +	} +  	nvbe->bound = false;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 10656a6be8e6..e1710640a278 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -341,7 +341,7 @@ nouveau_card_init_channel(struct drm_device *dev)  	gpuobj = NULL;  	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, -				     0, nouveau_mem_fb_amount(dev), +				     0, dev_priv->vram_size,  				     NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM,  				     &gpuobj);  	if (ret) @@ -427,6 +427,10 @@ nouveau_card_init(struct drm_device *dev)  			goto out;  	} +	ret = nouveau_mem_detect(dev); +	if (ret) +		goto out_bios; +  	ret = nouveau_gpuobj_early_init(dev);  	if (ret)  		goto out_bios; @@ -502,7 +506,7 @@ nouveau_card_init(struct drm_device *dev)  		else  			ret = nv04_display_create(dev);  		if (ret) -			goto out_irq; +			goto out_channel;  	}  	ret = nouveau_backlight_init(dev); @@ -516,6 +520,11 @@ nouveau_card_init(struct drm_device *dev)  	return 0; +out_channel: +	if (dev_priv->channel) { +		nouveau_channel_free(dev_priv->channel); +		dev_priv->channel = NULL; +	}  out_irq:  	drm_irq_uninstall(dev);  out_fifo: @@ -533,6 +542,7 @@ out_mc:  out_gpuobj:  	nouveau_gpuobj_takedown(dev);  out_mem: +	nouveau_sgdma_takedown(dev);  	nouveau_mem_close(dev);  out_instmem:  	engine->instmem.takedown(dev); diff --git a/drivers/gpu/drm/nouveau/nv40_fifo.c b/drivers/gpu/drm/nouveau/nv40_fifo.c index 6b2ef4a9fce1..500ccfd3a0b8 100644 --- a/drivers/gpu/drm/nouveau/nv40_fifo.c +++ b/drivers/gpu/drm/nouveau/nv40_fifo.c @@ -278,7 +278,7 @@ nv40_fifo_init_ramxx(struct drm_device *dev)  	default:  		nv_wr32(dev, 0x2230, 0);  		nv_wr32(dev, NV40_PFIFO_RAMFC, -			((nouveau_mem_fb_amount(dev) - 512 * 1024 + +			((dev_priv->vram_size - 512 * 1024 +  			  dev_priv->ramfc_offset) >> 16) | (3 << 16));  		break;  	} diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 53e8afe1dcd1..0616c96e4b67 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -335,6 +335,27 @@ nv40_graph_init(struct drm_device *dev)  	nv_wr32(dev, 0x400b38, 0x2ffff800);  	nv_wr32(dev, 0x400b3c, 0x00006000); +	/* Tiling related stuff. */ +	switch (dev_priv->chipset) { +	case 0x44: +	case 0x4a: +		nv_wr32(dev, 0x400bc4, 0x1003d888); +		nv_wr32(dev, 0x400bbc, 0xb7a7b500); +		break; +	case 0x46: +		nv_wr32(dev, 0x400bc4, 0x0000e024); +		nv_wr32(dev, 0x400bbc, 0xb7a7b520); +		break; +	case 0x4c: +	case 0x4e: +	case 0x67: +		nv_wr32(dev, 0x400bc4, 0x1003d888); +		nv_wr32(dev, 0x400bbc, 0xb7a7b540); +		break; +	default: +		break; +	} +  	/* Turn all the tiling regions off. */  	for (i = 0; i < pfb->num_tiles; i++)  		nv40_graph_set_region_tiling(dev, i, 0, 0, 0); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index fac6c88a2b1f..649db4c1b690 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -143,7 +143,7 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan)  	}  	ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, -				  0, nouveau_mem_fb_amount(dev)); +				  0, dev_priv->vram_size);  	if (ret) {  		nv50_evo_channel_del(pchan);  		return ret; @@ -231,7 +231,7 @@ nv50_display_init(struct drm_device *dev)  	/* This used to be in crtc unblank, but seems out of place there. */  	nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0);  	/* RAM is clamped to 256 MiB. */ -	ram_amount = nouveau_mem_fb_amount(dev); +	ram_amount = dev_priv->vram_size;  	NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount);  	if (ram_amount > 256*1024*1024)  		ram_amount = 256*1024*1024; @@ -529,8 +529,10 @@ int nv50_display_create(struct drm_device *dev)  	}  	ret = nv50_display_init(dev); -	if (ret) +	if (ret) { +		nv50_display_destroy(dev);  		return ret; +	}  	return 0;  } @@ -885,10 +887,12 @@ nv50_display_error_handler(struct drm_device *dev)  	nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000);  } -static void -nv50_display_irq_hotplug(struct drm_device *dev) +void +nv50_display_irq_hotplug_bh(struct work_struct *work)  { -	struct drm_nouveau_private *dev_priv = dev->dev_private; +	struct drm_nouveau_private *dev_priv = +		container_of(work, struct drm_nouveau_private, hpd_work); +	struct drm_device *dev = dev_priv->dev;  	struct drm_connector *connector;  	const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };  	uint32_t unplug_mask, plug_mask, change_mask; @@ -949,8 +953,10 @@ nv50_display_irq_handler(struct drm_device *dev)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	uint32_t delayed = 0; -	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) -		nv50_display_irq_hotplug(dev); +	if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { +		if (!work_pending(&dev_priv->hpd_work)) +			queue_work(dev_priv->wq, &dev_priv->hpd_work); +	}  	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {  		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h index 3ae8d0725f63..581d405ac014 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.h +++ b/drivers/gpu/drm/nouveau/nv50_display.h @@ -37,6 +37,7 @@  void nv50_display_irq_handler(struct drm_device *dev);  void nv50_display_irq_handler_bh(struct work_struct *work); +void nv50_display_irq_hotplug_bh(struct work_struct *work);  int nv50_display_init(struct drm_device *dev);  int nv50_display_create(struct drm_device *dev);  int nv50_display_destroy(struct drm_device *dev); diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 25a3cd8794f9..a8c70e7e9184 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -157,8 +157,11 @@ nv50_fbcon_accel_init(struct fb_info *info)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nouveau_channel *chan = dev_priv->channel;  	struct nouveau_gpuobj *eng2d = NULL; +	uint64_t fb;  	int ret, format; +	fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base; +  	switch (info->var.bits_per_pixel) {  	case 8:  		format = 0xf3; @@ -248,9 +251,8 @@ nv50_fbcon_accel_init(struct fb_info *info)  	OUT_RING(chan, info->fix.line_length);  	OUT_RING(chan, info->var.xres_virtual);  	OUT_RING(chan, info->var.yres_virtual); -	OUT_RING(chan, 0); -	OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + -			 dev_priv->vm_vram_base); +	OUT_RING(chan, upper_32_bits(fb)); +	OUT_RING(chan, lower_32_bits(fb));  	BEGIN_RING(chan, NvSub2D, 0x0230, 2);  	OUT_RING(chan, format);  	OUT_RING(chan, 1); @@ -258,9 +260,8 @@ nv50_fbcon_accel_init(struct fb_info *info)  	OUT_RING(chan, info->fix.line_length);  	OUT_RING(chan, info->var.xres_virtual);  	OUT_RING(chan, info->var.yres_virtual); -	OUT_RING(chan, 0); -	OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + -			 dev_priv->vm_vram_base); +	OUT_RING(chan, upper_32_bits(fb)); +	OUT_RING(chan, lower_32_bits(fb));  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c new file mode 100644 index 000000000000..c61782b314e7 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -0,0 +1,76 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_hw.h" + +static int +nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) +{ +	const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; + +	if (gpio->line > 32) +		return -EINVAL; + +	*reg = nv50_gpio_reg[gpio->line >> 3]; +	*shift = (gpio->line & 7) << 2; +	return 0; +} + +int +nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) +{ +	struct dcb_gpio_entry *gpio; +	uint32_t r, s, v; + +	gpio = nouveau_bios_gpio_entry(dev, tag); +	if (!gpio) +		return -ENOENT; + +	if (nv50_gpio_location(gpio, &r, &s)) +		return -EINVAL; + +	v = nv_rd32(dev, r) >> (s + 2); +	return ((v & 1) == (gpio->state[1] & 1)); +} + +int +nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) +{ +	struct dcb_gpio_entry *gpio; +	uint32_t r, s, v; + +	gpio = nouveau_bios_gpio_entry(dev, tag); +	if (!gpio) +		return -ENOENT; + +	if (nv50_gpio_location(gpio, &r, &s)) +		return -EINVAL; + +	v  = nv_rd32(dev, r) & ~(0x3 << s); +	v |= (gpio->state[state] ^ 2) << s; +	nv_wr32(dev, r, v); +	return 0; +} diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index c62b33a02f88..b203d06f601f 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -410,9 +410,10 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = {  	{ 0x5039, false, NULL }, /* m2mf */  	{ 0x502d, false, NULL }, /* 2d */  	{ 0x50c0, false, NULL }, /* compute */ +	{ 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */  	{ 0x5097, false, NULL }, /* tesla (nv50) */ -	{ 0x8297, false, NULL }, /* tesla (nv80/nv90) */ -	{ 0x8397, false, NULL }, /* tesla (nva0) */ -	{ 0x8597, false, NULL }, /* tesla (nva8) */ +	{ 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ +	{ 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ +	{ 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */  	{}  }; diff --git a/drivers/gpu/drm/nouveau/nv50_grctx.c b/drivers/gpu/drm/nouveau/nv50_grctx.c index 546b31949a30..42a8fb20c1e6 100644 --- a/drivers/gpu/drm/nouveau/nv50_grctx.c +++ b/drivers/gpu/drm/nouveau/nv50_grctx.c @@ -55,12 +55,12 @@  #define CP_FLAG_AUTO_LOAD             ((2 * 32) + 5)  #define CP_FLAG_AUTO_LOAD_NOT_PENDING 0  #define CP_FLAG_AUTO_LOAD_PENDING     1 +#define CP_FLAG_NEWCTX                ((2 * 32) + 10) +#define CP_FLAG_NEWCTX_BUSY           0 +#define CP_FLAG_NEWCTX_DONE           1  #define CP_FLAG_XFER                  ((2 * 32) + 11)  #define CP_FLAG_XFER_IDLE             0  #define CP_FLAG_XFER_BUSY             1 -#define CP_FLAG_NEWCTX                ((2 * 32) + 12) -#define CP_FLAG_NEWCTX_BUSY           0 -#define CP_FLAG_NEWCTX_DONE           1  #define CP_FLAG_ALWAYS                ((2 * 32) + 13)  #define CP_FLAG_ALWAYS_FALSE          0  #define CP_FLAG_ALWAYS_TRUE           1 @@ -177,6 +177,7 @@ nv50_grctx_init(struct nouveau_grctx *ctx)  	case 0x96:  	case 0x98:  	case 0xa0: +	case 0xa3:  	case 0xa5:  	case 0xa8:  	case 0xaa: @@ -364,6 +365,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)  	case 0xac:  		gr_def(ctx, 0x401c00, 0x042500df);  		break; +	case 0xa3:  	case 0xa5:  	case 0xa8:  		gr_def(ctx, 0x401c00, 0x142500df); @@ -418,6 +420,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)  		break;  	case 0x84:  	case 0xa0: +	case 0xa3:  	case 0xa5:  	case 0xa8:  	case 0xaa: @@ -792,6 +795,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)  				case 0xa5:  					gr_def(ctx, offset + 0x1c, 0x310c0000);  					break; +				case 0xa3:  				case 0xa8:  				case 0xaa:  				case 0xac: @@ -859,6 +863,8 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)  			else  				gr_def(ctx, offset + 0x8, 0x05010202);  			gr_def(ctx, offset + 0xc, 0x00030201); +			if (dev_priv->chipset == 0xa3) +				cp_ctx(ctx, base + 0x36c, 1);  			cp_ctx(ctx, base + 0x400, 2);  			gr_def(ctx, base + 0x404, 0x00000040); @@ -1159,7 +1165,9 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx)  		nv50_graph_construct_gene_unk8(ctx);  		if (dev_priv->chipset == 0xa0)  			xf_emit(ctx, 0x189, 0); -		else if (dev_priv->chipset < 0xa8) +		else if (dev_priv->chipset == 0xa3) +			xf_emit(ctx, 0xd5, 0); +		else if (dev_priv->chipset == 0xa5)  			xf_emit(ctx, 0x99, 0);  		else if (dev_priv->chipset == 0xaa)  			xf_emit(ctx, 0x65, 0); @@ -1197,6 +1205,8 @@ nv50_graph_construct_xfer1(struct nouveau_grctx *ctx)  		ctx->ctxvals_pos = offset + 4;  		if (dev_priv->chipset == 0xa0)  			xf_emit(ctx, 0xa80, 0); +		else if (dev_priv->chipset == 0xa3) +			xf_emit(ctx, 0xa7c, 0);  		else  			xf_emit(ctx, 0xa7a, 0);  		xf_emit(ctx, 1, 0x3fffff); @@ -1341,6 +1351,7 @@ nv50_graph_construct_gene_unk1(struct nouveau_grctx *ctx)  		xf_emit(ctx, 0x942, 0);  		break;  	case 0xa0: +	case 0xa3:  		xf_emit(ctx, 0x2042, 0);  		break;  	case 0xa5: diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index de1f5b0062c5..5f21df31f3aa 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -63,9 +63,10 @@ nv50_instmem_init(struct drm_device *dev)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nouveau_channel *chan;  	uint32_t c_offset, c_size, c_ramfc, c_vmpd, c_base, pt_size; +	uint32_t save_nv001700; +	uint64_t v;  	struct nv50_instmem_priv *priv;  	int ret, i; -	uint32_t v, save_nv001700;  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (!priv) @@ -76,17 +77,12 @@ nv50_instmem_init(struct drm_device *dev)  	for (i = 0x1700; i <= 0x1710; i += 4)  		priv->save1700[(i-0x1700)/4] = nv_rd32(dev, i); -	if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) -		dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10) << 12; -	else -		dev_priv->vram_sys_base = 0; -  	/* Reserve the last MiB of VRAM, we should probably try to avoid  	 * setting up the below tables over the top of the VBIOS image at  	 * some point.  	 */  	dev_priv->ramin_rsvd_vram = 1 << 20; -	c_offset = nouveau_mem_fb_amount(dev) - dev_priv->ramin_rsvd_vram; +	c_offset = dev_priv->vram_size - dev_priv->ramin_rsvd_vram;  	c_size   = 128 << 10;  	c_vmpd   = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x1400 : 0x200;  	c_ramfc  = ((dev_priv->chipset & 0xf0) == 0x50) ? 0x0 : 0x20; @@ -106,7 +102,7 @@ nv50_instmem_init(struct drm_device *dev)  	dev_priv->vm_gart_size = NV50_VM_BLOCK;  	dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; -	dev_priv->vm_vram_size = nouveau_mem_fb_amount(dev); +	dev_priv->vm_vram_size = dev_priv->vram_size;  	if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM)  		dev_priv->vm_vram_size = NV50_VM_MAX_VRAM;  	dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); @@ -189,8 +185,8 @@ nv50_instmem_init(struct drm_device *dev)  	i = 0;  	while (v < dev_priv->vram_sys_base + c_offset + c_size) { -		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, v); -		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, 0x00000000); +		BAR0_WI32(priv->pramin_pt->gpuobj, i + 0, lower_32_bits(v)); +		BAR0_WI32(priv->pramin_pt->gpuobj, i + 4, upper_32_bits(v));  		v += 0x1000;  		i += 8;  	} diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index c2fff543b06f..0c68698f23df 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -211,7 +211,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  			mode_ctl = 0x0200;  		break;  	case OUTPUT_DP: -		mode_ctl |= 0x00050000; +		mode_ctl |= (nv_encoder->dp.mc_unknown << 16);  		if (nv_encoder->dcb->sorconf.link & 1)  			mode_ctl |= 0x00000800;  		else @@ -274,6 +274,7 @@ static const struct drm_encoder_funcs nv50_sor_encoder_funcs = {  int  nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)  { +	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nouveau_encoder *nv_encoder = NULL;  	struct drm_encoder *encoder;  	bool dum; @@ -319,5 +320,27 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry)  	encoder->possible_crtcs = entry->heads;  	encoder->possible_clones = 0; +	if (nv_encoder->dcb->type == OUTPUT_DP) { +		uint32_t mc, or = nv_encoder->or; + +		if (dev_priv->chipset < 0x90 || +		    dev_priv->chipset == 0x92 || dev_priv->chipset == 0xa0) +			mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(or)); +		else +			mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(or)); + +		switch ((mc & 0x00000f00) >> 8) { +		case 8: +		case 9: +			nv_encoder->dp.mc_unknown = (mc & 0x000f0000) >> 16; +			break; +		default: +			break; +		} + +		if (!nv_encoder->dp.mc_unknown) +			nv_encoder->dp.mc_unknown = 5; +	} +  	return 0;  } diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 07b7ebf1f466..bcec2d79636e 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1137,6 +1137,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32  	int len, ws, ps, ptr;  	unsigned char op;  	atom_exec_context ectx; +	int ret = 0;  	if (!base)  		return -EINVAL; @@ -1169,7 +1170,8 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32  		if (ectx.abort) {  			DRM_ERROR("atombios stuck executing %04X (len %d, WS %d, PS %d) @ 0x%04X\n",  				base, len, ws, ps, ptr - 1); -			return -EINVAL; +			ret = -EINVAL; +			goto free;  		}  		if (op < ATOM_OP_CNT && op > 0) @@ -1184,9 +1186,10 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32  	debug_depth--;  	SDEBUG("<<\n"); +free:  	if (ws)  		kfree(ectx.ws); -	return 0; +	return ret;  }  int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 561048a7c0a4..2b9affe754ce 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -325,11 +325,12 @@ void r300_gpu_init(struct radeon_device *rdev)  	r100_hdp_reset(rdev);  	/* FIXME: rv380 one pipes ? */ -	if ((rdev->family == CHIP_R300) || (rdev->family == CHIP_R350)) { +	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) || +	    (rdev->family == CHIP_R350)) {  		/* r300,r350 */  		rdev->num_gb_pipes = 2;  	} else { -		/* rv350,rv370,rv380 */ +		/* rv350,rv370,rv380,r300 AD */  		rdev->num_gb_pipes = 1;  	}  	rdev->num_z_pipes = 1; diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 1fff95505cf5..5673665ff216 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -69,16 +69,19 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_dev  	struct radeon_i2c_bus_rec i2c;  	int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);  	struct _ATOM_GPIO_I2C_INFO *i2c_info; -	uint16_t data_offset; -	int i; +	uint16_t data_offset, size; +	int i, num_indices;  	memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));  	i2c.valid = false; -	if (atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { +	if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {  		i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); -		for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { +		num_indices = (size - sizeof(ATOM_COMMON_TABLE_HEADER)) / +			sizeof(ATOM_GPIO_I2C_ASSIGMENT); + +		for (i = 0; i < num_indices; i++) {  			gpio = &i2c_info->asGPIO_Info[i];  			if (gpio->sucI2cId.ucAccess == id) { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 2becdeda68a3..37db8adb2748 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -760,7 +760,9 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct  			dac = RBIOS8(dac_info + 0x3) & 0xf;  			p_dac->ps2_pdac_adj = (bg << 8) | (dac);  		} -		found = 1; +		/* if the values are all zeros, use the table */ +		if (p_dac->ps2_pdac_adj) +			found = 1;  	}  	if (!found) /* fallback to defaults */ @@ -895,7 +897,9 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct  			bg = RBIOS8(dac_info + 0x10) & 0xf;  			dac = RBIOS8(dac_info + 0x11) & 0xf;  			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); -			found = 1; +			/* if the values are all zeros, use the table */ +			if (tv_dac->ps2_tvdac_adj) +				found = 1;  		} else if (rev > 1) {  			bg = RBIOS8(dac_info + 0xc) & 0xf;  			dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf; @@ -908,7 +912,9 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct  			bg = RBIOS8(dac_info + 0xe) & 0xf;  			dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;  			tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); -			found = 1; +			/* if the values are all zeros, use the table */ +			if (tv_dac->ps2_tvdac_adj) +				found = 1;  		}  		tv_dac->tv_std = radeon_combios_get_tv_info(rdev);  	} @@ -925,7 +931,9 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct  				    (bg << 16) | (dac << 20);  				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;  				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; -				found = 1; +				/* if the values are all zeros, use the table */ +				if (tv_dac->ps2_tvdac_adj) +					found = 1;  			} else {  				bg = RBIOS8(dac_info + 0x4) & 0xf;  				dac = RBIOS8(dac_info + 0x5) & 0xf; @@ -933,7 +941,9 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct  				    (bg << 16) | (dac << 20);  				tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;  				tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; -				found = 1; +				/* if the values are all zeros, use the table */ +				if (tv_dac->ps2_tvdac_adj) +					found = 1;  			}  		} else {  			DRM_INFO("No TV DAC info found in BIOS\n"); diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 60d59816b94f..3fba50540f72 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -315,7 +315,7 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr  		radeon_encoder = to_radeon_encoder(encoder);  		if (!radeon_encoder->enc_priv)  			return 0; -		if (rdev->is_atom_bios) { +		if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) {  			struct radeon_encoder_atom_dac *dac_int;  			dac_int = radeon_encoder->enc_priv;  			dac_int->tv_std = val; diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index dc6eba6b96dd..419630dd2075 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -417,8 +417,9 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv)  	return -EBUSY;  } -static void radeon_init_pipes(drm_radeon_private_t *dev_priv) +static void radeon_init_pipes(struct drm_device *dev)  { +	drm_radeon_private_t *dev_priv = dev->dev_private;  	uint32_t gb_tile_config, gb_pipe_sel = 0;  	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) { @@ -436,11 +437,12 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)  		dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;  	} else {  		/* R3xx */ -		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || +		if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 && +		     dev->pdev->device != 0x4144) ||  		    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350)) {  			dev_priv->num_gb_pipes = 2;  		} else { -			/* R3Vxx */ +			/* RV3xx/R300 AD */  			dev_priv->num_gb_pipes = 1;  		}  	} @@ -736,7 +738,7 @@ static int radeon_do_engine_reset(struct drm_device * dev)  	/* setup the raster pipes */  	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300) -	    radeon_init_pipes(dev_priv); +	    radeon_init_pipes(dev);  	/* Reset the CP ring */  	radeon_do_cp_reset(dev_priv); diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 52d6f96f274b..c52fc3080b67 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -317,12 +317,8 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	DAC_ENCODER_CONTROL_PS_ALLOCATION args; -	int index = 0, num = 0; +	int index = 0;  	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; -	enum radeon_tv_std tv_std = TV_STD_NTSC; - -	if (dac_info->tv_std) -		tv_std = dac_info->tv_std;  	memset(&args, 0, sizeof(args)); @@ -330,12 +326,10 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)  	case ENCODER_OBJECT_ID_INTERNAL_DAC1:  	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:  		index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); -		num = 1;  		break;  	case ENCODER_OBJECT_ID_INTERNAL_DAC2:  	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:  		index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); -		num = 2;  		break;  	} @@ -346,7 +340,7 @@ atombios_dac_setup(struct drm_encoder *encoder, int action)  	else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))  		args.ucDacStandard = ATOM_DAC1_CV;  	else { -		switch (tv_std) { +		switch (dac_info->tv_std) {  		case TV_STD_PAL:  		case TV_STD_PAL_M:  		case TV_STD_SCART_PAL: @@ -377,10 +371,6 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)  	TV_ENCODER_CONTROL_PS_ALLOCATION args;  	int index = 0;  	struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv; -	enum radeon_tv_std tv_std = TV_STD_NTSC; - -	if (dac_info->tv_std) -		tv_std = dac_info->tv_std;  	memset(&args, 0, sizeof(args)); @@ -391,7 +381,7 @@ atombios_tv_setup(struct drm_encoder *encoder, int action)  	if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))  		args.sTVEncoder.ucTvStandard = ATOM_TV_CV;  	else { -		switch (tv_std) { +		switch (dac_info->tv_std) {  		case TV_STD_NTSC:  			args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;  			break; @@ -1558,12 +1548,14 @@ static const struct drm_encoder_funcs radeon_atom_enc_funcs = {  struct radeon_encoder_atom_dac *  radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)  { +	struct drm_device *dev = radeon_encoder->base.dev; +	struct radeon_device *rdev = dev->dev_private;  	struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);  	if (!dac)  		return NULL; -	dac->tv_std = TV_STD_NTSC; +	dac->tv_std = radeon_atombios_get_tv_info(rdev);  	return dac;  } @@ -1641,6 +1633,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su  		break;  	case ENCODER_OBJECT_ID_INTERNAL_DAC1:  		drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); +		radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);  		drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);  		break;  	case ENCODER_OBJECT_ID_INTERNAL_DAC2: diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index cf389ce50a8a..2441cca7d775 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -830,8 +830,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)  				crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;  			if (rdev->family == CHIP_R420 || -					rdev->family == CHIP_R423 || -					rdev->family == CHIP_RV410) +			    rdev->family == CHIP_R423 || +			    rdev->family == CHIP_RV410)  				tv_dac_cntl |= (R420_TV_DAC_RDACPD |  						R420_TV_DAC_GDACPD |  						R420_TV_DAC_BDACPD | @@ -907,35 +907,43 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,  	if (rdev->family != CHIP_R200) {  		tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);  		if (rdev->family == CHIP_R420 || -				rdev->family == CHIP_R423 || -				rdev->family == CHIP_RV410) { +		    rdev->family == CHIP_R423 || +		    rdev->family == CHIP_RV410) {  			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | -					RADEON_TV_DAC_BGADJ_MASK | -					R420_TV_DAC_DACADJ_MASK | -					R420_TV_DAC_RDACPD | -					R420_TV_DAC_GDACPD | -					R420_TV_DAC_BDACPD | -					R420_TV_DAC_TVENABLE); +					 RADEON_TV_DAC_BGADJ_MASK | +					 R420_TV_DAC_DACADJ_MASK | +					 R420_TV_DAC_RDACPD | +					 R420_TV_DAC_GDACPD | +					 R420_TV_DAC_BDACPD | +					 R420_TV_DAC_TVENABLE);  		} else {  			tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | -					RADEON_TV_DAC_BGADJ_MASK | -					RADEON_TV_DAC_DACADJ_MASK | -					RADEON_TV_DAC_RDACPD | -					RADEON_TV_DAC_GDACPD | -					RADEON_TV_DAC_BDACPD); +					 RADEON_TV_DAC_BGADJ_MASK | +					 RADEON_TV_DAC_DACADJ_MASK | +					 RADEON_TV_DAC_RDACPD | +					 RADEON_TV_DAC_GDACPD | +					 RADEON_TV_DAC_BDACPD);  		} -		/*  FIXME TV */ -		if (tv_dac) { -			struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; -			tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | -					RADEON_TV_DAC_NHOLD | -					RADEON_TV_DAC_STD_PS2 | -					tv_dac->ps2_tvdac_adj); +		tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD; + +		if (is_tv) { +			if (tv_dac->tv_std == TV_STD_NTSC || +			    tv_dac->tv_std == TV_STD_NTSC_J || +			    tv_dac->tv_std == TV_STD_PAL_M || +			    tv_dac->tv_std == TV_STD_PAL_60) +				tv_dac_cntl |= tv_dac->ntsc_tvdac_adj; +			else +				tv_dac_cntl |= tv_dac->pal_tvdac_adj; + +			if (tv_dac->tv_std == TV_STD_NTSC || +			    tv_dac->tv_std == TV_STD_NTSC_J) +				tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; +			else +				tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;  		} else -			tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | -					RADEON_TV_DAC_NHOLD | -					RADEON_TV_DAC_STD_PS2); +			tv_dac_cntl |= (RADEON_TV_DAC_STD_PS2 | +					tv_dac->ps2_tvdac_adj);  		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);  	}  | 
