diff options
Diffstat (limited to 'drivers/gpu/drm')
101 files changed, 1362 insertions, 687 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 23120c00a88..90e28081712 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -22,6 +22,7 @@ menuconfig DRM  config DRM_USB  	tristate  	depends on DRM +	depends on USB_ARCH_HAS_HCD  	select USB  config DRM_KMS_HELPER diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index d0c4574ef49..36164806b9d 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -193,6 +193,9 @@ static const struct file_operations ast_fops = {  	.mmap = ast_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.read = drm_read,  }; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 7282c081fb5..a712cafcfa1 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev)  	ast->cursor_cache = obj;  	ast->cursor_cache_gpu_addr = gpu_addr; -	DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr); +	DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);  	return 0;  fail:  	return ret; diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 7053140c659..b83a2d7ddd1 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = {  	.unlocked_ioctl = drm_ioctl,  	.mmap = cirrus_mmap,  	.poll = drm_poll, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.fasync = drm_fasync,  };  static struct drm_driver driver = { diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 08a7aa722d6..6fbfc244748 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,  	if (!drm_core_check_feature(dev, DRIVER_MODESET))  		return -EINVAL; -	if (!req->flags) +	if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))  		return -EINVAL;  	mutex_lock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a8743c399e8..b7ee230572b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -87,6 +87,9 @@ static struct edid_quirk {  	int product_id;  	u32 quirks;  } edid_quirk_list[] = { +	/* ASUS VW222S */ +	{ "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING }, +  	/* Acer AL1706 */  	{ "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },  	/* Acer F51 */ diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 66d4a28ad5a..0303935d10e 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -119,7 +119,7 @@ static int edid_load(struct drm_connector *connector, char *name,  {  	const struct firmware *fw;  	struct platform_device *pdev; -	u8 *fwdata = NULL, *edid; +	u8 *fwdata = NULL, *edid, *new_edid;  	int fwsize, expected;  	int builtin = 0, err = 0;  	int i, valid_extensions = 0; @@ -195,12 +195,14 @@ static int edid_load(struct drm_connector *connector, char *name,  		    "\"%s\" for connector \"%s\"\n", valid_extensions,  		    edid[0x7e], name, connector_name);  		edid[0x7e] = valid_extensions; -		edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, +		new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,  		    GFP_KERNEL); -		if (edid == NULL) { +		if (new_edid == NULL) {  			err = -ENOMEM; +			kfree(edid);  			goto relfw_out;  		} +		edid = new_edid;  	}  	connector->display_info.raw_edid = edid; diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index b7adb4a967f..28637c181b1 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -706,9 +706,6 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)  	p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);  	p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);  	p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal); - -	p->crtc_hadjusted = false; -	p->crtc_vadjusted = false;  }  EXPORT_SYMBOL(drm_mode_set_crtcinfo); diff --git a/drivers/gpu/drm/drm_proc.c b/drivers/gpu/drm/drm_proc.c index 371c695322d..da457b18eaa 100644 --- a/drivers/gpu/drm/drm_proc.c +++ b/drivers/gpu/drm/drm_proc.c @@ -89,7 +89,7 @@ static const struct file_operations drm_proc_fops = {   * Create a given set of proc files represented by an array of   * gdm_proc_lists in the given root directory.   */ -int drm_proc_create_files(struct drm_info_list *files, int count, +static int drm_proc_create_files(struct drm_info_list *files, int count,  			  struct proc_dir_entry *root, struct drm_minor *minor)  {  	struct drm_device *dev = minor->dev; @@ -172,7 +172,7 @@ int drm_proc_init(struct drm_minor *minor, int minor_id,  	return 0;  } -int drm_proc_remove_files(struct drm_info_list *files, int count, +static int drm_proc_remove_files(struct drm_info_list *files, int count,  			  struct drm_minor *minor)  {  	struct list_head *pos, *q; diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 7f5096763b7..59a26e577b5 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI  config DRM_EXYNOS_G2D  	bool "Exynos DRM G2D" -	depends on DRM_EXYNOS +	depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D  	help  	  Choose this option if you want to use Exynos G2D for DRM. diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 613bf8a5d9b..ae13febe0ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c @@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,  	/* TODO */  } +static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, +	struct vm_area_struct *vma) +{ +	return -ENOTTY; +} +  static struct dma_buf_ops exynos_dmabuf_ops = {  	.map_dma_buf		= exynos_gem_map_dma_buf,  	.unmap_dma_buf		= exynos_gem_unmap_dma_buf, @@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = {  	.kmap_atomic		= exynos_gem_dmabuf_kmap_atomic,  	.kunmap			= exynos_gem_dmabuf_kunmap,  	.kunmap_atomic		= exynos_gem_dmabuf_kunmap_atomic, +	.mmap			= exynos_gem_dmabuf_mmap,  	.release		= exynos_dmabuf_release,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index ebacec6f1e4..d0707193745 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)  	if (!file_priv)  		return -ENOMEM; -	drm_prime_init_file_private(&file->prime);  	file->driver_priv = file_priv;  	return exynos_drm_subdrv_open(dev, file); @@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev,  			e->base.destroy(&e->base);  		}  	} -	drm_prime_destroy_file_private(&file->prime);  	spin_unlock_irqrestore(&dev->event_lock, flags);  	exynos_drm_subdrv_close(dev, file); @@ -241,6 +239,9 @@ static const struct file_operations exynos_drm_driver_fops = {  	.poll		= drm_poll,  	.read		= drm_read,  	.unlocked_ioctl	= drm_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.release	= drm_release,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a68d2b313f0..b19cd93e704 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "failed to find registers\n"); -		ret = -ENOENT; -		goto err_clk; -	}  	ctx->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!ctx->regs) { diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index d2d88f22a03..1065e90d091 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -129,7 +129,6 @@ struct g2d_runqueue_node {  struct g2d_data {  	struct device			*dev;  	struct clk			*gate_clk; -	struct resource			*regs_res;  	void __iomem			*regs;  	int				irq;  	struct workqueue_struct		*g2d_workq; @@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	struct exynos_drm_subdrv *subdrv;  	int ret; -	g2d = kzalloc(sizeof(*g2d), GFP_KERNEL); +	g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL);  	if (!g2d) {  		dev_err(dev, "failed to allocate driver data\n");  		return -ENOMEM; @@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",  			sizeof(struct g2d_runqueue_node), 0, 0, NULL); -	if (!g2d->runqueue_slab) { -		ret = -ENOMEM; -		goto err_free_mem; -	} +	if (!g2d->runqueue_slab) +		return -ENOMEM;  	g2d->dev = dev; @@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	pm_runtime_enable(dev);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_err(dev, "failed to get I/O memory\n"); -		ret = -ENOENT; -		goto err_put_clk; -	} -	g2d->regs_res = request_mem_region(res->start, resource_size(res), -					   dev_name(dev)); -	if (!g2d->regs_res) { -		dev_err(dev, "failed to request I/O memory\n"); -		ret = -ENOENT; -		goto err_put_clk; -	} - -	g2d->regs = ioremap(res->start, resource_size(res)); +	g2d->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!g2d->regs) {  		dev_err(dev, "failed to remap I/O memory\n");  		ret = -ENXIO; -		goto err_release_res; +		goto err_put_clk;  	}  	g2d->irq = platform_get_irq(pdev, 0);  	if (g2d->irq < 0) {  		dev_err(dev, "failed to get irq\n");  		ret = g2d->irq; -		goto err_unmap_base; +		goto err_put_clk;  	} -	ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d); +	ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0, +								"drm_g2d", g2d);  	if (ret < 0) {  		dev_err(dev, "irq request failed\n"); -		goto err_unmap_base; +		goto err_put_clk;  	}  	platform_set_drvdata(pdev, g2d); @@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	ret = exynos_drm_subdrv_register(subdrv);  	if (ret < 0) {  		dev_err(dev, "failed to register drm g2d device\n"); -		goto err_free_irq; +		goto err_put_clk;  	}  	dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", @@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev)  	return 0; -err_free_irq: -	free_irq(g2d->irq, g2d); -err_unmap_base: -	iounmap(g2d->regs); -err_release_res: -	release_resource(g2d->regs_res); -	kfree(g2d->regs_res);  err_put_clk:  	pm_runtime_disable(dev);  	clk_put(g2d->gate_clk); @@ -862,8 +840,6 @@ err_destroy_workqueue:  	destroy_workqueue(g2d->g2d_workq);  err_destroy_slab:  	kmem_cache_destroy(g2d->runqueue_slab); -err_free_mem: -	kfree(g2d);  	return ret;  } @@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev)  	cancel_work_sync(&g2d->runqueue_work);  	exynos_drm_subdrv_unregister(&g2d->subdrv); -	free_irq(g2d->irq, g2d);  	while (g2d->runqueue_node) {  		g2d_free_runqueue_node(g2d, g2d->runqueue_node);  		g2d->runqueue_node = g2d_get_runqueue_node(g2d);  	} -	iounmap(g2d->regs); -	release_resource(g2d->regs_res); -	kfree(g2d->regs_res); -  	pm_runtime_disable(&pdev->dev);  	clk_put(g2d->gate_clk);  	g2d_fini_cmdlist(g2d);  	destroy_workqueue(g2d->g2d_workq);  	kmem_cache_destroy(g2d->runqueue_slab); -	kfree(g2d);  	return 0;  } @@ -924,7 +894,7 @@ static int g2d_resume(struct device *dev)  }  #endif -SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); +static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);  struct platform_driver g2d_driver = {  	.probe		= g2d_probe, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index f9efde40c09..a38051c95ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -122,7 +122,7 @@ fail:  		__free_page(pages[i]);  	drm_free_large(pages); -	return ERR_PTR(PTR_ERR(p)); +	return ERR_CAST(p);  }  static void exynos_gem_put_pages(struct drm_gem_object *obj, @@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,  	 */  	args->pitch = args->width * ((args->bpp + 7) / 8); -	args->size = PAGE_ALIGN(args->pitch * args->height); +	args->size = args->pitch * args->height;  	exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);  	if (IS_ERR(exynos_gem_obj)) diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 8ffcdf8b9e2..3fdf0b65f47 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);  	if (!ctx) {  		DRM_LOG_KMS("failed to alloc common hdmi context.\n");  		return -ENOMEM; @@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__);  	exynos_drm_subdrv_unregister(&ctx->subdrv); -	kfree(ctx);  	return 0;  } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index b89829e5043..e1f94b746bd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -29,7 +29,6 @@ static const uint32_t formats[] = {  	DRM_FORMAT_XRGB8888,  	DRM_FORMAT_ARGB8888,  	DRM_FORMAT_NV12, -	DRM_FORMAT_NV12M,  	DRM_FORMAT_NV12MT,  }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index bb1550c4dd5..537027a74fd 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev)  	DRM_DEBUG_KMS("%s\n", __FILE__); -	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);  	if (!ctx)  		return -ENOMEM; @@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev)  		ctx->raw_edid = NULL;  	} -	kfree(ctx); -  	return 0;  } diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 409e2ec1207..a6aea6f3ea1 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)  	DRM_DEBUG_KMS("HDMI resource init\n"); -	memset(res, 0, sizeof *res); +	memset(res, 0, sizeof(*res));  	/* get clocks, power */  	res->hdmi = clk_get(dev, "hdmi"); @@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)  	clk_set_parent(res->sclk_hdmi, res->sclk_pixel);  	res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * -		sizeof res->regul_bulk[0], GFP_KERNEL); +		sizeof(res->regul_bulk[0]), GFP_KERNEL);  	if (!res->regul_bulk) {  		DRM_ERROR("failed to get memory for regulators\n");  		goto fail; @@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata)  		clk_put(res->sclk_hdmi);  	if (!IS_ERR_OR_NULL(res->hdmi))  		clk_put(res->hdmi); -	memset(res, 0, sizeof *res); +	memset(res, 0, sizeof(*res));  	return 0;  } @@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev)  	}  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		DRM_ERROR("failed to find registers\n"); -		ret = -ENOENT; -		goto err_resource; -	}  	hdata->regs = devm_request_and_ioremap(&pdev->dev, res);  	if (!hdata->regs) { diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 30fcc12f81d..25b97d5e5fc 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res,  static void vp_default_filter(struct mixer_resources *res)  {  	vp_filter_set(res, VP_POLY8_Y0_LL, -		filter_y_horiz_tap8, sizeof filter_y_horiz_tap8); +		filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));  	vp_filter_set(res, VP_POLY4_Y0_LL, -		filter_y_vert_tap4, sizeof filter_y_vert_tap4); +		filter_y_vert_tap4, sizeof(filter_y_vert_tap4));  	vp_filter_set(res, VP_POLY4_C0_LL, -		filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4); +		filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));  }  static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 0f9b7db80f6..cf49ba5a54b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = {  		.pos = DSPAPOS,  		.surf = DSPASURF,  		.addr = MRST_DSPABASE, +		.base = MRST_DSPABASE,  		.status = PIPEASTAT,  		.linoff = DSPALINOFF,  		.tileoff = DSPATILEOFF, @@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = {  		.pos = DSPBPOS,  		.surf = DSPBSURF,  		.addr = DSPBBASE, +		.base = DSPBBASE,  		.status = PIPEBSTAT,  		.linoff = DSPBLINOFF,  		.tileoff = DSPBTILEOFF, diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 30dc22a7156..8033526bb53 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1362,6 +1362,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,  	    (struct drm_connector **) (psb_intel_crtc + 1);  	psb_intel_crtc->mode_set.num_connectors = 0;  	psb_intel_cursor_init(dev, psb_intel_crtc); + +	/* Set to true so that the pipe is forced off on initial config. */ +	psb_intel_crtc->active = true;  }  int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 57d892eaaa6..463ec6871fe 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = {  	.unlocked_ioctl = drm_ioctl,  	.mmap = i810_mmap_buffers,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index f9924ad04d0..48cfcca2b35 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9cf7dfe022b..914c0dfabe6 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	spin_lock_init(&dev_priv->irq_lock);  	spin_lock_init(&dev_priv->error_lock);  	spin_lock_init(&dev_priv->rps_lock); +	spin_lock_init(&dev_priv->dpio_lock);  	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))  		dev_priv->num_pipe = 3; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ed22612bc84..a24ffbe97c0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -346,11 +346,40 @@ static const struct pci_device_id pciidlist[] = {		/* aka */  	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */  	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */  	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ +	INTEL_VGA_DEVICE(0x0422, &intel_haswell_d_info), /* GT2 desktop */  	INTEL_VGA_DEVICE(0x040a, &intel_haswell_d_info), /* GT1 server */  	INTEL_VGA_DEVICE(0x041a, &intel_haswell_d_info), /* GT2 server */ +	INTEL_VGA_DEVICE(0x042a, &intel_haswell_d_info), /* GT2 server */  	INTEL_VGA_DEVICE(0x0406, &intel_haswell_m_info), /* GT1 mobile */  	INTEL_VGA_DEVICE(0x0416, &intel_haswell_m_info), /* GT2 mobile */ -	INTEL_VGA_DEVICE(0x0c16, &intel_haswell_d_info), /* SDV */ +	INTEL_VGA_DEVICE(0x0426, &intel_haswell_m_info), /* GT2 mobile */ +	INTEL_VGA_DEVICE(0x0C02, &intel_haswell_d_info), /* SDV GT1 desktop */ +	INTEL_VGA_DEVICE(0x0C12, &intel_haswell_d_info), /* SDV GT2 desktop */ +	INTEL_VGA_DEVICE(0x0C22, &intel_haswell_d_info), /* SDV GT2 desktop */ +	INTEL_VGA_DEVICE(0x0C0A, &intel_haswell_d_info), /* SDV GT1 server */ +	INTEL_VGA_DEVICE(0x0C1A, &intel_haswell_d_info), /* SDV GT2 server */ +	INTEL_VGA_DEVICE(0x0C2A, &intel_haswell_d_info), /* SDV GT2 server */ +	INTEL_VGA_DEVICE(0x0C06, &intel_haswell_m_info), /* SDV GT1 mobile */ +	INTEL_VGA_DEVICE(0x0C16, &intel_haswell_m_info), /* SDV GT2 mobile */ +	INTEL_VGA_DEVICE(0x0C26, &intel_haswell_m_info), /* SDV GT2 mobile */ +	INTEL_VGA_DEVICE(0x0A02, &intel_haswell_d_info), /* ULT GT1 desktop */ +	INTEL_VGA_DEVICE(0x0A12, &intel_haswell_d_info), /* ULT GT2 desktop */ +	INTEL_VGA_DEVICE(0x0A22, &intel_haswell_d_info), /* ULT GT2 desktop */ +	INTEL_VGA_DEVICE(0x0A0A, &intel_haswell_d_info), /* ULT GT1 server */ +	INTEL_VGA_DEVICE(0x0A1A, &intel_haswell_d_info), /* ULT GT2 server */ +	INTEL_VGA_DEVICE(0x0A2A, &intel_haswell_d_info), /* ULT GT2 server */ +	INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ +	INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ +	INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ +	INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ +	INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ +	INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ +	INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ +	INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ +	INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ +	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ +	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ +	INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */  	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5c4657a54f9..489e2b162b2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2365,6 +2365,10 @@ int i915_gpu_idle(struct drm_device *dev)  	/* Flush everything onto the inactive list. */  	for_each_ring(ring, dev_priv, i) { +		ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); +		if (ret) +			return ret; +  		ret = i915_ring_idle(ring);  		if (ret)  			return ret; @@ -2372,10 +2376,6 @@ int i915_gpu_idle(struct drm_device *dev)  		/* Is the device fubar? */  		if (WARN_ON(!list_empty(&ring->gpu_write_list)))  			return -EBUSY; - -		ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID); -		if (ret) -			return ret;  	}  	return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index da8b01fb1bf..a9d58d72bb4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -451,7 +451,6 @@ int i915_switch_context(struct intel_ring_buffer *ring,  	struct drm_i915_file_private *file_priv = NULL;  	struct i915_hw_context *to;  	struct drm_i915_gem_object *from_obj = ring->last_context_obj; -	int ret;  	if (dev_priv->hw_contexts_disabled)  		return 0; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 5af631e788c..ff2819ea081 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -291,6 +291,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  	target_i915_obj = to_intel_bo(target_obj);  	target_offset = target_i915_obj->gtt_offset; +	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and +	 * pipe_control writes because the gpu doesn't properly redirect them +	 * through the ppgtt for non_secure batchbuffers. */ +	if (unlikely(IS_GEN6(dev) && +	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && +	    !target_i915_obj->has_global_gtt_mapping)) { +		i915_gem_gtt_bind_object(target_i915_obj, +					 target_i915_obj->cache_level); +	} +  	/* The target buffer should have appeared before us in the  	 * exec_object list, so it should have a GTT space bound by now.  	 */ @@ -399,16 +409,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		io_mapping_unmap_atomic(reloc_page);  	} -	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and -	 * pipe_control writes because the gpu doesn't properly redirect them -	 * through the ppgtt for non_secure batchbuffers. */ -	if (unlikely(IS_GEN6(dev) && -	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && -	    !target_i915_obj->has_global_gtt_mapping)) { -		i915_gem_gtt_bind_object(target_i915_obj, -					 target_i915_obj->cache_level); -	} -  	/* and update the user's relocation entry */  	reloc->presumed_offset = target_offset; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9fd25a43553..60815b861ec 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)  	/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024  	 * entries. For aliasing ppgtt support we just steal them at the end for  	 * now. */ -	first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES; +	first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES;  	ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);  	if (!ppgtt) @@ -261,7 +261,10 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt,  		pte_flags |= GEN6_PTE_CACHE_LLC;  		break;  	case I915_CACHE_NONE: -		pte_flags |= GEN6_PTE_UNCACHED; +		if (IS_HASWELL(dev)) +			pte_flags |= HSW_PTE_UNCACHED; +		else +			pte_flags |= GEN6_PTE_UNCACHED;  		break;  	default:  		BUG(); @@ -361,7 +364,8 @@ int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)  	struct drm_device *dev = obj->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	if (dev_priv->mm.gtt->needs_dmar) +	/* don't map imported dma buf objects */ +	if (dev_priv->mm.gtt->needs_dmar && !obj->sg_table)  		return intel_gtt_map_memory(obj->pages,  					    obj->base.size >> PAGE_SHIFT,  					    &obj->sg_list, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8a3828528b9..5249640cce1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev)  			dev->driver->irq_handler = i8xx_irq_handler;  			dev->driver->irq_uninstall = i8xx_irq_uninstall;  		} else if (INTEL_INFO(dev)->gen == 3) { -			/* IIR "flip pending" means done if this bit is set */ -			I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE)); -  			dev->driver->irq_preinstall = i915_irq_preinstall;  			dev->driver->irq_postinstall = i915_irq_postinstall;  			dev->driver->irq_uninstall = i915_irq_uninstall; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index acc99b21e0b..28725ce5b82 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -115,6 +115,7 @@  #define GEN6_PTE_VALID			(1 << 0)  #define GEN6_PTE_UNCACHED		(1 << 1) +#define HSW_PTE_UNCACHED		(0)  #define GEN6_PTE_CACHE_LLC		(2 << 1)  #define GEN6_PTE_CACHE_LLC_MLC		(3 << 1)  #define GEN6_PTE_CACHE_BITS		(3 << 1) diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2f5388af8df..7631807a278 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -32,6 +32,7 @@  #include "intel_drv.h"  #include "i915_drv.h" +#ifdef CONFIG_PM  static u32 calc_residency(struct drm_device *dev, const u32 reg)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -224,3 +225,14 @@ void i915_teardown_sysfs(struct drm_device *dev)  	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);  	sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);  } +#else +void i915_setup_sysfs(struct drm_device *dev) +{ +	return; +} + +void i915_teardown_sysfs(struct drm_device *dev) +{ +	return; +} +#endif /* CONFIG_PM */ diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 7ed4a41c396..23bdc8cd145 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -326,6 +326,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)  	return ret;  } +static struct edid *intel_crt_get_edid(struct drm_connector *connector, +				struct i2c_adapter *i2c) +{ +	struct edid *edid; + +	edid = drm_get_edid(connector, i2c); + +	if (!edid && !intel_gmbus_is_forced_bit(i2c)) { +		DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); +		intel_gmbus_force_bit(i2c, true); +		edid = drm_get_edid(connector, i2c); +		intel_gmbus_force_bit(i2c, false); +	} + +	return edid; +} + +/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ +static int intel_crt_ddc_get_modes(struct drm_connector *connector, +				struct i2c_adapter *adapter) +{ +	struct edid *edid; + +	edid = intel_crt_get_edid(connector, adapter); +	if (!edid) +		return 0; + +	return intel_connector_update_modes(connector, edid); +} +  static bool intel_crt_detect_ddc(struct drm_connector *connector)  {  	struct intel_crt *crt = intel_attached_crt(connector); @@ -336,7 +366,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)  	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); -	edid = drm_get_edid(connector, i2c); +	edid = intel_crt_get_edid(connector, i2c);  	if (edid) {  		bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; @@ -544,13 +574,13 @@ static int intel_crt_get_modes(struct drm_connector *connector)  	struct i2c_adapter *i2c;  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); -	ret = intel_ddc_get_modes(connector, i2c); +	ret = intel_crt_ddc_get_modes(connector, i2c);  	if (ret || !IS_G4X(dev))  		return ret;  	/* Try to probe digital port for output in DVI-I -> VGA mode. */  	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); -	return intel_ddc_get_modes(connector, i2c); +	return intel_crt_ddc_get_modes(connector, i2c);  }  static int intel_crt_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f6159765f1e..bc2ad348e5d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -869,6 +869,7 @@ intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc,  	unsigned long bestppm, ppm, absppm;  	int dotclk, flag; +	flag = 0;  	dotclk = target * 1000;  	bestppm = 1000000;  	ppm = absppm = 0; @@ -1375,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,  	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",  	     reg, pipe_name(pipe)); -	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), +	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0 +	     && (val & DP_PIPEB_SELECT),  	     "IBX PCH dp port still using transcoder B\n");  } @@ -1383,11 +1385,12 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,  				     enum pipe pipe, int reg)  {  	u32 val = I915_READ(reg); -	WARN(hdmi_pipe_enabled(dev_priv, val, pipe), +	WARN(hdmi_pipe_enabled(dev_priv, pipe, val),  	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",  	     reg, pipe_name(pipe)); -	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT), +	WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0 +	     && (val & SDVO_PIPE_B_SELECT),  	     "IBX PCH hdmi port still using transcoder B\n");  } @@ -1403,13 +1406,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,  	reg = PCH_ADPA;  	val = I915_READ(reg); -	WARN(adpa_pipe_enabled(dev_priv, val, pipe), +	WARN(adpa_pipe_enabled(dev_priv, pipe, val),  	     "PCH VGA enabled on transcoder %c, should be disabled\n",  	     pipe_name(pipe));  	reg = PCH_LVDS;  	val = I915_READ(reg); -	WARN(lvds_pipe_enabled(dev_priv, val, pipe), +	WARN(lvds_pipe_enabled(dev_priv, pipe, val),  	     "PCH LVDS enabled on transcoder %c, should be disabled\n",  	     pipe_name(pipe)); @@ -1871,7 +1874,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv,  			     enum pipe pipe, int reg)  {  	u32 val = I915_READ(reg); -	if (hdmi_pipe_enabled(dev_priv, val, pipe)) { +	if (hdmi_pipe_enabled(dev_priv, pipe, val)) {  		DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",  			      reg, pipe);  		I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1893,12 +1896,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,  	reg = PCH_ADPA;  	val = I915_READ(reg); -	if (adpa_pipe_enabled(dev_priv, val, pipe)) +	if (adpa_pipe_enabled(dev_priv, pipe, val))  		I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);  	reg = PCH_LVDS;  	val = I915_READ(reg); -	if (lvds_pipe_enabled(dev_priv, val, pipe)) { +	if (lvds_pipe_enabled(dev_priv, pipe, val)) {  		DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val);  		I915_WRITE(reg, val & ~LVDS_PORT_EN);  		POSTING_READ(reg); @@ -3753,17 +3756,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  			continue;  		} -		if (intel_encoder->type == INTEL_OUTPUT_EDP) { -			/* Use VBT settings if we have an eDP panel */ -			unsigned int edp_bpc = dev_priv->edp.bpp / 3; - -			if (edp_bpc < display_bpc) { -				DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); -				display_bpc = edp_bpc; -			} -			continue; -		} -  		/* Not one of the known troublemakers, check the EDID */  		list_for_each_entry(connector, &dev->mode_config.connector_list,  				    head) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0a56b9ab0f5..ace757af913 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1174,10 +1174,14 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp)  	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");  	pp = ironlake_get_pp_control(dev_priv); -	pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); +	/* We need to switch off panel power _and_ force vdd, for otherwise some +	 * panels get very unhappy and cease to work. */ +	pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);  	I915_WRITE(PCH_PP_CONTROL, pp);  	POSTING_READ(PCH_PP_CONTROL); +	intel_dp->want_panel_vdd = false; +  	ironlake_wait_panel_off(intel_dp);  } @@ -1287,11 +1291,9 @@ static void intel_dp_prepare(struct drm_encoder *encoder)  	 * ensure that we have vdd while we switch off the panel. */  	ironlake_edp_panel_vdd_on(intel_dp);  	ironlake_edp_backlight_off(intel_dp); -	ironlake_edp_panel_off(intel_dp); -  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); +	ironlake_edp_panel_off(intel_dp);  	intel_dp_link_down(intel_dp); -	ironlake_edp_panel_vdd_off(intel_dp, false);  }  static void intel_dp_commit(struct drm_encoder *encoder) @@ -1326,11 +1328,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  		/* Switching the panel off requires vdd. */  		ironlake_edp_panel_vdd_on(intel_dp);  		ironlake_edp_backlight_off(intel_dp); -		ironlake_edp_panel_off(intel_dp); -  		intel_dp_sink_dpms(intel_dp, mode); +		ironlake_edp_panel_off(intel_dp);  		intel_dp_link_down(intel_dp); -		ironlake_edp_panel_vdd_off(intel_dp, false);  		if (is_cpu_edp(intel_dp))  			ironlake_edp_pll_off(encoder); @@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)  			break;  	} -	intel_dp_i2c_init(intel_dp, intel_connector, name); -  	/* Cache some DPCD data in the eDP case */  	if (is_edp(intel_dp)) { -		bool ret;  		struct edp_power_seq	cur, vbt;  		u32 pp_on, pp_off, pp_div; -		struct edid *edid;  		pp_on = I915_READ(PCH_PP_ON_DELAYS);  		pp_off = I915_READ(PCH_PP_OFF_DELAYS); @@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)  		DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",  			      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); +	} + +	intel_dp_i2c_init(intel_dp, intel_connector, name); + +	if (is_edp(intel_dp)) { +		bool ret; +		struct edid *edid;  		ironlake_edp_panel_vdd_on(intel_dp);  		ret = intel_dp_get_dpcd(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 84353559441..cd54cf88a28 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -46,15 +46,16 @@  })  #define wait_for_atomic_us(COND, US) ({ \ -	int i, ret__ = -ETIMEDOUT;	\ -	for (i = 0; i < (US); i++) {	\ -		if ((COND)) {		\ -			ret__ = 0;	\ -			break;		\ -		}			\ -		udelay(1);		\ -	}				\ -	ret__;				\ +	unsigned long timeout__ = jiffies + usecs_to_jiffies(US);	\ +	int ret__ = 0;							\ +	while (!(COND)) {						\ +		if (time_after(jiffies, timeout__)) {			\ +			ret__ = -ETIMEDOUT;				\ +			break;						\ +		}							\ +		cpu_relax();						\ +	}								\ +	ret__;								\  })  #define wait_for(COND, MS) _wait_for(COND, MS, 1) @@ -341,6 +342,8 @@ struct intel_fbc_work {  	int interval;  }; +int intel_connector_update_modes(struct drm_connector *connector, +				struct edid *edid);  int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);  extern void intel_attach_force_audio_property(struct drm_connector *connector); @@ -380,7 +383,6 @@ extern void intel_pch_panel_fitting(struct drm_device *dev,  				    const struct drm_display_mode *mode,  				    struct drm_display_mode *adjusted_mode);  extern u32 intel_panel_get_max_backlight(struct drm_device *dev); -extern u32 intel_panel_get_backlight(struct drm_device *dev);  extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);  extern int intel_panel_setup_backlight(struct drm_device *dev);  extern void intel_panel_enable_backlight(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 1991a4408cf..b9755f6378d 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -486,9 +486,6 @@ int intel_setup_gmbus(struct drm_device *dev)  		bus->dev_priv = dev_priv;  		bus->adapter.algo = &gmbus_algorithm; -		ret = i2c_add_adapter(&bus->adapter); -		if (ret) -			goto err;  		/* By default use a conservative clock rate */  		bus->reg0 = port | GMBUS_RATE_100KHZ; @@ -498,6 +495,10 @@ int intel_setup_gmbus(struct drm_device *dev)  			bus->force_bit = true;  		intel_gpio_setup(bus, port); + +		ret = i2c_add_adapter(&bus->adapter); +		if (ret) +			goto err;  	}  	intel_i2c_reset(dev_priv->dev); @@ -540,9 +541,6 @@ void intel_teardown_gmbus(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	int i; -	if (dev_priv->gmbus == NULL) -		return; -  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i];  		i2c_del_adapter(&bus->adapter); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e05c0d3e344..e9a6f6aaed8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -780,6 +780,14 @@ static const struct dmi_system_id intel_no_lvds[] = {  			DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),  		},  	}, +	{ +		.callback = intel_no_lvds_dmi_callback, +		.ident = "Gigabyte GA-D525TUD", +		.matches = { +			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), +			DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), +		}, +	},  	{ }	/* terminating entry */  }; diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 45848b9b670..29b72593fbb 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -33,6 +33,25 @@  #include "i915_drv.h"  /** + * intel_connector_update_modes - update connector from edid + * @connector: DRM connector device to use + * @edid: previously read EDID information + */ +int intel_connector_update_modes(struct drm_connector *connector, +				struct edid *edid) +{ +	int ret; + +	drm_mode_connector_update_edid_property(connector, edid); +	ret = drm_add_edid_modes(connector, edid); +	drm_edid_to_eld(connector, edid); +	connector->display_info.raw_edid = NULL; +	kfree(edid); + +	return ret; +} + +/**   * intel_ddc_get_modes - get modelist from monitor   * @connector: DRM connector device to use   * @adapter: i2c adapter @@ -43,18 +62,12 @@ int intel_ddc_get_modes(struct drm_connector *connector,  			struct i2c_adapter *adapter)  {  	struct edid *edid; -	int ret = 0;  	edid = drm_get_edid(connector, adapter); -	if (edid) { -		drm_mode_connector_update_edid_property(connector, edid); -		ret = drm_add_edid_modes(connector, edid); -		drm_edid_to_eld(connector, edid); -		connector->display_info.raw_edid = NULL; -		kfree(edid); -	} +	if (!edid) +		return 0; -	return ret; +	return intel_connector_update_modes(connector, edid);  }  static const struct drm_prop_enum_list force_audio_names[] = { diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 10c7d39034e..e019b236986 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)  	return val;  } -u32 intel_panel_get_max_backlight(struct drm_device *dev) +static u32 _intel_panel_get_max_backlight(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 max;  	max = i915_read_blc_pwm_ctl(dev_priv); -	if (max == 0) { -		/* XXX add code here to query mode clock or hardware clock -		 * and program max PWM appropriately. -		 */ -		pr_warn_once("fixme: max PWM is zero\n"); -		return 1; -	}  	if (HAS_PCH_SPLIT(dev)) {  		max >>= 16; @@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)  			max *= 0xff;  	} +	return max; +} + +u32 intel_panel_get_max_backlight(struct drm_device *dev) +{ +	u32 max; + +	max = _intel_panel_get_max_backlight(dev); +	if (max == 0) { +		/* XXX add code here to query mode clock or hardware clock +		 * and program max PWM appropriately. +		 */ +		pr_warn_once("fixme: max PWM is zero\n"); +		return 1; +	} +  	DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);  	return max;  } @@ -213,7 +222,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val)  	return val;  } -u32 intel_panel_get_backlight(struct drm_device *dev) +static u32 intel_panel_get_backlight(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 val; @@ -311,9 +320,6 @@ void intel_panel_enable_backlight(struct drm_device *dev,  	if (dev_priv->backlight_level == 0)  		dev_priv->backlight_level = intel_panel_get_max_backlight(dev); -	dev_priv->backlight_enabled = true; -	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); -  	if (INTEL_INFO(dev)->gen >= 4) {  		uint32_t reg, tmp; @@ -326,7 +332,7 @@ void intel_panel_enable_backlight(struct drm_device *dev,  		 * we don't track the backlight dpms state, hence check whether  		 * we have to do anything first. */  		if (tmp & BLM_PWM_ENABLE) -			return; +			goto set_level;  		if (dev_priv->num_pipe == 3)  			tmp &= ~BLM_PIPE_SELECT_IVB; @@ -347,6 +353,14 @@ void intel_panel_enable_backlight(struct drm_device *dev,  			I915_WRITE(BLC_PWM_PCH_CTL1, tmp);  		}  	} + +set_level: +	/* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. +	 * BLC_PWM_CPU_CTL may be cleared to zero automatically when these +	 * registers are set. +	 */ +	dev_priv->backlight_enabled = true; +	intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);  }  static void intel_panel_init_backlight(struct drm_device *dev) @@ -419,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev)  	memset(&props, 0, sizeof(props));  	props.type = BACKLIGHT_RAW; -	props.max_brightness = intel_panel_get_max_backlight(dev); +	props.max_brightness = _intel_panel_get_max_backlight(dev); +	if (props.max_brightness == 0) { +		DRM_ERROR("Failed to get maximum backlight value\n"); +		return -ENODEV; +	}  	dev_priv->backlight =  		backlight_device_register("intel_backlight",  					  &connector->kdev, dev, diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 94aabcaa3a6..ba8a27b1757 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2441,17 +2441,10 @@ static void gen6_enable_rps(struct drm_device *dev)  		   dev_priv->max_delay << 24 |  		   dev_priv->min_delay << 16); -	if (IS_HASWELL(dev)) { -		I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); -		I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); -		I915_WRITE(GEN6_RP_UP_EI, 66000); -		I915_WRITE(GEN6_RP_DOWN_EI, 350000); -	} else { -		I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); -		I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); -		I915_WRITE(GEN6_RP_UP_EI, 100000); -		I915_WRITE(GEN6_RP_DOWN_EI, 5000000); -	} +	I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); +	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); +	I915_WRITE(GEN6_RP_UP_EI, 66000); +	I915_WRITE(GEN6_RP_DOWN_EI, 350000);  	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);  	I915_WRITE(GEN6_RP_CONTROL, @@ -3679,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev)  	if (IS_PINEVIEW(dev))  		I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY)); + +	/* IIR "flip pending" means done if this bit is set */ +	I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));  }  static void i85x_init_clock_gating(struct drm_device *dev) @@ -3963,6 +3959,7 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)  		DRM_ERROR("Force wake wait timed out\n");  	I915_WRITE_NOTRACE(FORCEWAKE, 1); +	POSTING_READ(FORCEWAKE);  	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))  		DRM_ERROR("Force wake wait timed out\n"); @@ -3983,6 +3980,7 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)  		DRM_ERROR("Force wake wait timed out\n");  	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1)); +	POSTING_READ(FORCEWAKE_MT);  	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))  		DRM_ERROR("Force wake wait timed out\n"); @@ -4018,14 +4016,14 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)  static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)  {  	I915_WRITE_NOTRACE(FORCEWAKE, 0); -	/* The below doubles as a POSTING_READ */ +	POSTING_READ(FORCEWAKE);  	gen6_gt_check_fifodbg(dev_priv);  }  static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)  {  	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1)); -	/* The below doubles as a POSTING_READ */ +	POSTING_READ(FORCEWAKE_MT);  	gen6_gt_check_fifodbg(dev_priv);  } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index bf0195a96d5..e2a73b38abe 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -227,31 +227,36 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring,  	 * number of bits based on the write domains has little performance  	 * impact.  	 */ -	flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; -	flags |= PIPE_CONTROL_TLB_INVALIDATE; -	flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; -	flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; -	flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; -	/* -	 * Ensure that any following seqno writes only happen when the render -	 * cache is indeed flushed (but only if the caller actually wants that). -	 */ -	if (flush_domains) +	if (flush_domains) { +		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; +		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; +		/* +		 * Ensure that any following seqno writes only happen +		 * when the render cache is indeed flushed. +		 */  		flags |= PIPE_CONTROL_CS_STALL; +	} +	if (invalidate_domains) { +		flags |= PIPE_CONTROL_TLB_INVALIDATE; +		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; +		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; +		/* +		 * TLB invalidate requires a post-sync write. +		 */ +		flags |= PIPE_CONTROL_QW_WRITE; +	} -	ret = intel_ring_begin(ring, 6); +	ret = intel_ring_begin(ring, 4);  	if (ret)  		return ret; -	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(5)); +	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));  	intel_ring_emit(ring, flags);  	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT); -	intel_ring_emit(ring, 0); /* lower dword */ -	intel_ring_emit(ring, 0); /* uppwer dword */ -	intel_ring_emit(ring, MI_NOOP); +	intel_ring_emit(ring, 0);  	intel_ring_advance(ring);  	return 0; @@ -289,8 +294,6 @@ static int init_ring_common(struct intel_ring_buffer *ring)  	I915_WRITE_HEAD(ring, 0);  	ring->write_tail(ring, 0); -	/* Initialize the ring. */ -	I915_WRITE_START(ring, obj->gtt_offset);  	head = I915_READ_HEAD(ring) & HEAD_ADDR;  	/* G45 ring initialization fails to reset head to zero */ @@ -316,6 +319,11 @@ static int init_ring_common(struct intel_ring_buffer *ring)  		}  	} +	/* Initialize the ring. This must happen _after_ we've cleared the ring +	 * registers with the above sequence (the readback of the HEAD registers +	 * also enforces ordering), otherwise the hw might lose the new ring +	 * register values. */ +	I915_WRITE_START(ring, obj->gtt_offset);  	I915_WRITE_CTL(ring,  			((ring->size - PAGE_SIZE) & RING_NR_PAGES)  			| RING_VALID); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 26a6a4d0d07..123afd35761 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -444,13 +444,16 @@ static bool intel_sdvo_write_cmd(struct intel_sdvo *intel_sdvo, u8 cmd,  	struct i2c_msg *msgs;  	int i, ret = true; +        /* Would be simpler to allocate both in one go ? */          	buf = (u8 *)kzalloc(args_len * 2 + 2, GFP_KERNEL);  	if (!buf)  		return false;  	msgs = kcalloc(args_len + 3, sizeof(*msgs), GFP_KERNEL); -	if (!msgs) +	if (!msgs) { +	        kfree(buf);  		return false; +        }  	intel_sdvo_debug_write(intel_sdvo, cmd, args, args_len); @@ -1689,6 +1692,7 @@ static bool intel_sdvo_detect_hdmi_audio(struct drm_connector *connector)  	edid = intel_sdvo_get_edid(connector);  	if (edid != NULL && edid->input & DRM_EDID_INPUT_DIGITAL)  		has_audio = drm_detect_monitor_audio(edid); +	kfree(edid);  	return has_audio;  } @@ -2569,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  		hotplug_mask = intel_sdvo->is_sdvob ?  			SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;  	} -	dev_priv->hotplug_supported_mask |= hotplug_mask;  	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2577,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))  		goto err; -	/* Set up hotplug command - note paranoia about contents of reply. -	 * We assume that the hardware is in a sane state, and only touch -	 * the bits we think we understand. -	 */ -	intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, -			     &intel_sdvo->hotplug_active, 2); -	intel_sdvo->hotplug_active[0] &= ~0x3; -  	if (intel_sdvo_output_setup(intel_sdvo,  				    intel_sdvo->caps.output_flags) != true) {  		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", @@ -2592,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  		goto err;  	} +	/* Only enable the hotplug irq if we need it, to work around noisy +	 * hotplug lines. +	 */ +	if (intel_sdvo->hotplug_active[0]) +		dev_priv->hotplug_supported_mask |= hotplug_mask; +  	intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);  	/* Set the input timing to the screen. Assume always input 0. */ diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index cc8df4de2d9..7644f31a377 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -60,11 +60,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,  	switch (fb->pixel_format) {  	case DRM_FORMAT_XBGR8888: -		sprctl |= SPRITE_FORMAT_RGBX888; +		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;  		pixel_size = 4;  		break;  	case DRM_FORMAT_XRGB8888: -		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; +		sprctl |= SPRITE_FORMAT_RGBX888;  		pixel_size = 4;  		break;  	case DRM_FORMAT_YUYV: diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index ea1024d7997..e5f145d2cb3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = {  	.mmap = mgag200_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.read = drm_read,  }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a4d7c500c97..b69642d5d85 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -468,10 +468,11 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  {  	unsigned int vcomax, vcomin, pllreffreq;  	unsigned int delta, tmpdelta; -	unsigned int testr, testn, testm, testo; +	int testr, testn, testm, testo;  	unsigned int p, m, n; -	unsigned int computed; +	unsigned int computed, vco;  	int tmp; +	const unsigned int m_div_val[] = { 1, 2, 4, 8 };  	m = n = p = 0;  	vcomax = 1488000; @@ -490,12 +491,13 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)  				if (delta == 0)  					break;  				for (testo = 5; testo < 33; testo++) { -					computed = pllreffreq * (testn + 1) / +					vco = pllreffreq * (testn + 1) /  						(testr + 1); -					if (computed < vcomin) +					if (vco < vcomin)  						continue; -					if (computed > vcomax) +					if (vco > vcomax)  						continue; +					computed = vco / (m_div_val[testm] * (testo + 1));  					if (computed > clock)  						tmpdelta = computed - clock;  					else diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index fc841e87b34..26ebffebe71 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -211,11 +211,6 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id,  	return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);  } -static int nouveau_dsm_init(void) -{ -	return 0; -} -  static int nouveau_dsm_get_client_id(struct pci_dev *pdev)  {  	/* easy option one - intel vendor ID means Integrated */ @@ -232,7 +227,6 @@ static int nouveau_dsm_get_client_id(struct pci_dev *pdev)  static struct vga_switcheroo_handler nouveau_dsm_handler = {  	.switchto = nouveau_dsm_switchto,  	.power_state = nouveau_dsm_power_state, -	.init = nouveau_dsm_init,  	.get_client_id = nouveau_dsm_get_client_id,  }; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 69688ef5cf4..7e16dc5e646 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,  	args->size = args->pitch * args->height;  	args->size = roundup(args->size, PAGE_SIZE); -	ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); +	ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index 77e564667b5..240cf962c99 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -229,7 +229,7 @@ nouveau_i2c_init(struct drm_device *dev)  			}  			break;  		case 6: /* NV50- DP AUX */ -			port->drive = entry[0]; +			port->drive = entry[0] & 0x0f;  			port->sense = port->drive;  			port->adapter.algo = &nouveau_dp_i2c_algo;  			break; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 1cdfd6e757c..c61014442aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -731,15 +731,16 @@ nouveau_card_init(struct drm_device *dev)  			case 0xa3:  			case 0xa5:  			case 0xa8: -			case 0xaf:  				nva3_copy_create(dev);  				break;  			}  			break;  		case NV_C0: -			nvc0_copy_create(dev, 1); +			if (!(nv_rd32(dev, 0x022500) & 0x00000200)) +				nvc0_copy_create(dev, 1);  		case NV_D0: -			nvc0_copy_create(dev, 0); +			if (!(nv_rd32(dev, 0x022500) & 0x00000100)) +				nvc0_copy_create(dev, 0);  			break;  		default:  			break; diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c index f429e6a8ca7..f0349053489 100644 --- a/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -115,6 +115,9 @@ nv50_gpio_init(struct drm_device *dev)  {  	struct drm_nouveau_private *dev_priv = dev->dev_private; +	/* initialise gpios and routing to vbios defaults */ +	nouveau_gpio_reset(dev); +  	/* disable, and ack any pending gpio interrupts */  	nv_wr32(dev, 0xe050, 0x00000000);  	nv_wr32(dev, 0xe054, 0xffffffff); diff --git a/drivers/gpu/drm/nouveau/nv84_fifo.c b/drivers/gpu/drm/nouveau/nv84_fifo.c index cc82d799fc3..c564c5e4c30 100644 --- a/drivers/gpu/drm/nouveau/nv84_fifo.c +++ b/drivers/gpu/drm/nouveau/nv84_fifo.c @@ -117,17 +117,22 @@ nv84_fifo_context_del(struct nouveau_channel *chan, int engine)  	struct drm_device *dev = chan->dev;  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	unsigned long flags; +	u32 save;  	/* remove channel from playlist, will context switch if active */  	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);  	nv_mask(dev, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000);  	nv50_fifo_playlist_update(dev); +	save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +  	/* tell any engines on this channel to unload their contexts */  	nv_wr32(dev, 0x0032fc, chan->ramin->vinst >> 12);  	if (!nv_wait_ne(dev, 0x0032fc, 0xffffffff, 0xffffffff))  		NV_INFO(dev, "PFIFO: channel %d unload timeout\n", chan->id); +	nv_wr32(dev, 0x002520, save); +  	nv_wr32(dev, 0x002600 + (chan->id * 4), 0x00000000);  	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); @@ -184,10 +189,13 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend)  	struct drm_nouveau_private *dev_priv = dev->dev_private;  	struct nv84_fifo_priv *priv = nv_engine(dev, engine);  	int i; +	u32 save;  	/* set playlist length to zero, fifo will unload context */  	nv_wr32(dev, 0x0032ec, 0); +	save = nv_mask(dev, 0x002520, 0x0000003f, 0x15); +  	/* tell all connected engines to unload their contexts */  	for (i = 0; i < priv->base.channels; i++) {  		struct nouveau_channel *chan = dev_priv->channels.ptr[i]; @@ -199,6 +207,7 @@ nv84_fifo_fini(struct drm_device *dev, int engine, bool suspend)  		}  	} +	nv_wr32(dev, 0x002520, save);  	nv_wr32(dev, 0x002140, 0);  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/nvc0_pm.c b/drivers/gpu/drm/nouveau/nvc0_pm.c index 7c95c44e288..4e712b10ebd 100644 --- a/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -557,7 +557,7 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info)  	nouveau_mem_exec(&exec, info->perflvl);  	if (dev_priv->chipset < 0xd0) -		nv_wr32(dev, 0x611200, 0x00003300); +		nv_wr32(dev, 0x611200, 0x00003330);  	else  		nv_wr32(dev, 0x62c000, 0x03030300);  } diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index d0d60e1e7f9..8a2fc89b776 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)  	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);  	int ch = EVO_CURS(nv_crtc->index); -	evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); +	evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff));  	evo_piow(crtc->dev, ch, 0x0080, 0x00000000);  	return 0;  } @@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,  	case OUTPUT_DP:  		if (nv_connector->base.display_info.bpc == 6) {  			nv_encoder->dp.datarate = mode->clock * 18 / 8; -			syncs |= 0x00000140; +			syncs |= 0x00000002 << 6;  		} else {  			nv_encoder->dp.datarate = mode->clock * 24 / 8; -			syncs |= 0x00000180; +			syncs |= 0x00000005 << 6;  		}  		if (nv_encoder->dcb->sorconf.link & 1) diff --git a/drivers/gpu/drm/nouveau/nve0_fifo.c b/drivers/gpu/drm/nouveau/nve0_fifo.c index 1855ecbd843..e98d144e6eb 100644 --- a/drivers/gpu/drm/nouveau/nve0_fifo.c +++ b/drivers/gpu/drm/nouveau/nve0_fifo.c @@ -294,6 +294,25 @@ nve0_fifo_isr_vm_fault(struct drm_device *dev, int unit)  	printk(" on channel 0x%010llx\n", (u64)inst << 12);  } +static int +nve0_fifo_page_flip(struct drm_device *dev, u32 chid) +{ +	struct nve0_fifo_priv *priv = nv_engine(dev, NVOBJ_ENGINE_FIFO); +	struct drm_nouveau_private *dev_priv = dev->dev_private; +	struct nouveau_channel *chan = NULL; +	unsigned long flags; +	int ret = -EINVAL; + +	spin_lock_irqsave(&dev_priv->channels.lock, flags); +	if (likely(chid >= 0 && chid < priv->base.channels)) { +		chan = dev_priv->channels.ptr[chid]; +		if (likely(chan)) +			ret = nouveau_finish_page_flip(chan, NULL); +	} +	spin_unlock_irqrestore(&dev_priv->channels.lock, flags); +	return ret; +} +  static void  nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  { @@ -303,11 +322,21 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)  	u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;  	u32 subc = (addr & 0x00070000);  	u32 mthd = (addr & 0x00003ffc); +	u32 show = stat; + +	if (stat & 0x00200000) { +		if (mthd == 0x0054) { +			if (!nve0_fifo_page_flip(dev, chid)) +				show &= ~0x00200000; +		} +	} -	NV_INFO(dev, "PSUBFIFO %d:", unit); -	nouveau_bitfield_print(nve0_fifo_subfifo_intr, stat); -	NV_INFO(dev, "PSUBFIFO %d: ch %d subc %d mthd 0x%04x data 0x%08x\n", -		unit, chid, subc, mthd, data); +	if (show) { +		NV_INFO(dev, "PFIFO%d:", unit); +		nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); +		NV_INFO(dev, "PFIFO%d: ch %d subc %d mthd 0x%04x data 0x%08x\n", +			unit, chid, subc, mthd, data); +	}  	nv_wr32(dev, 0x0400c0 + (unit * 0x2000), 0x80600008);  	nv_wr32(dev, 0x040108 + (unit * 0x2000), stat); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 9e6f76fec52..e721e3087b9 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,8 +258,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  		radeon_crtc->enabled = true;  		/* adjust pm to dpms changes BEFORE enabling crtcs */  		radeon_pm_compute_clocks(rdev); -		/* disable crtc pair power gating before programming */ -		if (ASIC_IS_DCE6(rdev)) +		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)  			atombios_powergate_crtc(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_ENABLE);  		if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)  			atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);  		atombios_enable_crtc(crtc, ATOM_DISABLE);  		radeon_crtc->enabled = false; -		/* power gating is per-pair */ -		if (ASIC_IS_DCE6(rdev)) { -			struct drm_crtc *other_crtc; -			struct radeon_crtc *other_radeon_crtc; -			list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { -				other_radeon_crtc = to_radeon_crtc(other_crtc); -				if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || -				    ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || -				    ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || -				    ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || -				    ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || -				    ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { -					/* if both crtcs in the pair are off, enable power gating */ -					if (other_radeon_crtc->enabled == false) -						atombios_powergate_crtc(crtc, ATOM_ENABLE); -					break; -				} -			} -		} +		if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) +			atombios_powergate_crtc(crtc, ATOM_ENABLE);  		/* adjust pm to dpms changes AFTER disabling crtcs */  		radeon_pm_compute_clocks(rdev);  		break; @@ -444,11 +426,28 @@ union atom_enable_ss {  static void atombios_crtc_program_ss(struct radeon_device *rdev,  				     int enable,  				     int pll_id, +				     int crtc_id,  				     struct radeon_atom_ss *ss)  { +	unsigned i;  	int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);  	union atom_enable_ss args; +	if (!enable) { +		for (i = 0; i < rdev->num_crtc; i++) { +			if (rdev->mode_info.crtcs[i] && +			    rdev->mode_info.crtcs[i]->enabled && +			    i != crtc_id && +			    pll_id == rdev->mode_info.crtcs[i]->pll_id) { +				/* one other crtc is using this pll don't turn +				 * off spread spectrum as it might turn off +				 * display on active crtc +				 */ +				return; +			} +		} +	} +  	memset(&args, 0, sizeof(args));  	if (ASIC_IS_DCE5(rdev)) { @@ -1028,7 +1027,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,  					  &ref_div, &post_div); -	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); +	atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,  				  encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1051,7 +1050,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode  			ss.step = step_size;  		} -		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); +		atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss);  	}  } @@ -1480,14 +1479,98 @@ static void radeon_legacy_atom_fixup(struct drm_crtc *crtc)  	}  } +/** + * radeon_get_pll_use_mask - look up a mask of which pplls are in use + * + * @crtc: drm crtc + * + * Returns the mask of which PPLLs (Pixel PLLs) are in use. + */ +static u32 radeon_get_pll_use_mask(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_crtc *test_crtc; +	struct radeon_crtc *radeon_test_crtc; +	u32 pll_in_use = 0; + +	list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { +		if (crtc == test_crtc) +			continue; + +		radeon_test_crtc = to_radeon_crtc(test_crtc); +		if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) +			pll_in_use |= (1 << radeon_test_crtc->pll_id); +	} +	return pll_in_use; +} + +/** + * radeon_get_shared_dp_ppll - return the PPLL used by another crtc for DP + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) used by another crtc/encoder which is + * also in DP mode.  For DP, a single PPLL can be used for all DP + * crtcs/encoders. + */ +static int radeon_get_shared_dp_ppll(struct drm_crtc *crtc) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_encoder *test_encoder; +	struct radeon_crtc *radeon_test_crtc; + +	list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { +		if (test_encoder->crtc && (test_encoder->crtc != crtc)) { +			if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { +				/* for DP use the same PLL for all */ +				radeon_test_crtc = to_radeon_crtc(test_encoder->crtc); +				if (radeon_test_crtc->pll_id != ATOM_PPLL_INVALID) +					return radeon_test_crtc->pll_id; +			} +		} +	} +	return ATOM_PPLL_INVALID; +} + +/** + * radeon_atom_pick_pll - Allocate a PPLL for use by the crtc. + * + * @crtc: drm crtc + * + * Returns the PPLL (Pixel PLL) to be used by the crtc.  For DP monitors + * a single PPLL can be used for all DP crtcs/encoders.  For non-DP + * monitors a dedicated PPLL must be used.  If a particular board has + * an external DP PLL, return ATOM_PPLL_INVALID to skip PLL programming + * as there is no need to program the PLL itself.  If we are not able to + * allocate a PLL, return ATOM_PPLL_INVALID to skip PLL programming to + * avoid messing up an existing monitor. + * + * Asic specific PLL information + * + * DCE 6.1 + * - PPLL2 is only available to UNIPHYA (both DP and non-DP) + * - PPLL0, PPLL1 are available for UNIPHYB/C/D/E/F (both DP and non-DP) + * + * DCE 6.0 + * - PPLL0 is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 5.0 + * - DCPLL is available to all UNIPHY (DP only) + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + * DCE 3.0/4.0/4.1 + * - PPLL1, PPLL2 are available for all UNIPHY (both DP and non-DP) and DAC + * + */  static int radeon_atom_pick_pll(struct drm_crtc *crtc)  {  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct drm_encoder *test_encoder; -	struct drm_crtc *test_crtc; -	uint32_t pll_in_use = 0; +	u32 pll_in_use; +	int pll;  	if (ASIC_IS_DCE61(rdev)) {  		list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) { @@ -1499,64 +1582,75 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)  				if ((test_radeon_encoder->encoder_id ==  				     ENCODER_OBJECT_ID_INTERNAL_UNIPHY) && -				    (dig->linkb == false)) /* UNIPHY A uses PPLL2 */ +				    (dig->linkb == false)) +					/* UNIPHY A uses PPLL2 */  					return ATOM_PPLL2; +				else if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { +					/* UNIPHY B/C/D/E/F */ +					if (rdev->clock.dp_extclk) +						/* skip PPLL programming if using ext clock */ +						return ATOM_PPLL_INVALID; +					else { +						/* use the same PPLL for all DP monitors */ +						pll = radeon_get_shared_dp_ppll(crtc); +						if (pll != ATOM_PPLL_INVALID) +							return pll; +					} +				} +				break;  			}  		}  		/* UNIPHY B/C/D/E/F */ -		list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { -			struct radeon_crtc *radeon_test_crtc; - -			if (crtc == test_crtc) -				continue; - -			radeon_test_crtc = to_radeon_crtc(test_crtc); -			if ((radeon_test_crtc->pll_id == ATOM_PPLL0) || -			    (radeon_test_crtc->pll_id == ATOM_PPLL1)) -				pll_in_use |= (1 << radeon_test_crtc->pll_id); -		} -		if (!(pll_in_use & 4)) +		pll_in_use = radeon_get_pll_use_mask(crtc); +		if (!(pll_in_use & (1 << ATOM_PPLL0)))  			return ATOM_PPLL0; -		return ATOM_PPLL1; +		if (!(pll_in_use & (1 << ATOM_PPLL1))) +			return ATOM_PPLL1; +		DRM_ERROR("unable to allocate a PPLL\n"); +		return ATOM_PPLL_INVALID;  	} else if (ASIC_IS_DCE4(rdev)) {  		list_for_each_entry(test_encoder, &dev->mode_config.encoder_list, head) {  			if (test_encoder->crtc && (test_encoder->crtc == crtc)) {  				/* in DP mode, the DP ref clock can come from PPLL, DCPLL, or ext clock,  				 * depending on the asic:  				 * DCE4: PPLL or ext clock -				 * DCE5: DCPLL or ext clock +				 * DCE5: PPLL, DCPLL, or ext clock +				 * DCE6: PPLL, PPLL0, or ext clock  				 *  				 * Setting ATOM_PPLL_INVALID will cause SetPixelClock to skip  				 * PPLL/DCPLL programming and only program the DP DTO for the  				 * crtc virtual pixel clock.  				 */  				if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { -					if (ASIC_IS_DCE5(rdev)) -						return ATOM_DCPLL; +					if (rdev->clock.dp_extclk) +						/* skip PPLL programming if using ext clock */ +						return ATOM_PPLL_INVALID;  					else if (ASIC_IS_DCE6(rdev)) +						/* use PPLL0 for all DP */  						return ATOM_PPLL0; -					else if (rdev->clock.dp_extclk) -						return ATOM_PPLL_INVALID; +					else if (ASIC_IS_DCE5(rdev)) +						/* use DCPLL for all DP */ +						return ATOM_DCPLL; +					else { +						/* use the same PPLL for all DP monitors */ +						pll = radeon_get_shared_dp_ppll(crtc); +						if (pll != ATOM_PPLL_INVALID) +							return pll; +					}  				} +				break;  			}  		} - -		/* otherwise, pick one of the plls */ -		list_for_each_entry(test_crtc, &dev->mode_config.crtc_list, head) { -			struct radeon_crtc *radeon_test_crtc; - -			if (crtc == test_crtc) -				continue; - -			radeon_test_crtc = to_radeon_crtc(test_crtc); -			if ((radeon_test_crtc->pll_id >= ATOM_PPLL1) && -			    (radeon_test_crtc->pll_id <= ATOM_PPLL2)) -				pll_in_use |= (1 << radeon_test_crtc->pll_id); -		} -		if (!(pll_in_use & 1)) +		/* all other cases */ +		pll_in_use = radeon_get_pll_use_mask(crtc); +		if (!(pll_in_use & (1 << ATOM_PPLL2))) +			return ATOM_PPLL2; +		if (!(pll_in_use & (1 << ATOM_PPLL1)))  			return ATOM_PPLL1; -		return ATOM_PPLL2; +		DRM_ERROR("unable to allocate a PPLL\n"); +		return ATOM_PPLL_INVALID;  	} else +		/* use PPLL1 or PPLL2 */  		return radeon_crtc->crtc_id;  } @@ -1572,11 +1666,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev)  								   ASIC_INTERNAL_SS_ON_DCPLL,  								   rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss);  		/* XXX: DCE5, make sure voltage, dispclk is high enough */  		atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk);  		if (ss_enabled) -			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); +			atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss);  	}  } @@ -1635,18 +1729,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,  static void atombios_crtc_prepare(struct drm_crtc *crtc)  {  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +	struct drm_device *dev = crtc->dev; +	struct radeon_device *rdev = dev->dev_private; +	radeon_crtc->in_mode_set = true;  	/* pick pll */  	radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); +	/* disable crtc pair power gating before programming */ +	if (ASIC_IS_DCE6(rdev)) +		atombios_powergate_crtc(crtc, ATOM_DISABLE); +  	atombios_lock_crtc(crtc, ATOM_ENABLE);  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);  }  static void atombios_crtc_commit(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); +  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);  	atombios_lock_crtc(crtc, ATOM_DISABLE); +	radeon_crtc->in_mode_set = false;  }  static void atombios_crtc_disable(struct drm_crtc *crtc) @@ -1655,9 +1759,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_atom_ss ss; +	int i;  	atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); +	for (i = 0; i < rdev->num_crtc; i++) { +		if (rdev->mode_info.crtcs[i] && +		    rdev->mode_info.crtcs[i]->enabled && +		    i != radeon_crtc->crtc_id && +		    radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { +			/* one other crtc is using this pll don't turn +			 * off the pll +			 */ +			goto done; +		} +	} +  	switch (radeon_crtc->pll_id) {  	case ATOM_PPLL1:  	case ATOM_PPLL2: @@ -1674,7 +1791,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)  	default:  		break;  	} -	radeon_crtc->pll_id = -1; +done: +	radeon_crtc->pll_id = ATOM_PPLL_INVALID;  }  static const struct drm_crtc_helper_funcs atombios_helper_funcs = { @@ -1723,6 +1841,6 @@ void radeon_atombios_init_crtc(struct drm_device *dev,  		else  			radeon_crtc->crtc_offset = 0;  	} -	radeon_crtc->pll_id = -1; +	radeon_crtc->pll_id = ATOM_PPLL_INVALID;  	drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);  } diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 7712cf5ab33..3623b98ed3f 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -577,30 +577,25 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);  	int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; +	u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); +	u8 tmp;  	if (!ASIC_IS_DCE4(rdev))  		return panel_mode; -	if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == -	    ENCODER_OBJECT_ID_NUTMEG) -		panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; -	else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == -		 ENCODER_OBJECT_ID_TRAVIS) { -		u8 id[6]; -		int i; -		for (i = 0; i < 6; i++) -			id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); -		if (id[0] == 0x73 && -		    id[1] == 0x69 && -		    id[2] == 0x76 && -		    id[3] == 0x61 && -		    id[4] == 0x72 && -		    id[5] == 0x54) +	if (dp_bridge != ENCODER_OBJECT_ID_NONE) { +		/* DP bridge chips */ +		tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); +		if (tmp & 1) +			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; +		else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || +			 (dp_bridge == ENCODER_OBJECT_ID_TRAVIS))  			panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;  		else -			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; +			panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;  	} else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { -		u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); +		/* eDP */ +		tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);  		if (tmp & 1)  			panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;  	} diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index f9bc27fe269..6e8803a1170 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)  	struct drm_device *dev = encoder->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); +	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); +	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;  	struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);  	struct radeon_connector *radeon_connector = NULL;  	struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)  	switch (mode) {  	case DRM_MODE_DPMS_ON: -		/* some early dce3.2 boards have a bug in their transmitter control table */ -		if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || -		    ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { -			if (ASIC_IS_DCE6(rdev)) { -				/* It seems we need to call ATOM_ENCODER_CMD_SETUP again -				 * before reenabling encoder on DPMS ON, otherwise we never -				 * get picture -				 */ -				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); +		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { +			if (!connector) +				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; +			else +				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + +			/* setup and enable the encoder */ +			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); +			atombios_dig_encoder_setup(encoder, +						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE, +						   dig->panel_mode); +			if (ext_encoder) { +				if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) +					atombios_external_encoder_setup(encoder, ext_encoder, +									EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);  			}  			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); -		} else { +		} else if (ASIC_IS_DCE4(rdev)) { +			/* setup and enable the encoder */ +			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); +			/* enable the transmitter */ +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);  			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); +		} else { +			/* setup and enable the encoder and transmitter */ +			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); +			/* some early dce3.2 boards have a bug in their transmitter control table */ +			if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) +				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);  		}  		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {  			if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { @@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)  	case DRM_MODE_DPMS_STANDBY:  	case DRM_MODE_DPMS_SUSPEND:  	case DRM_MODE_DPMS_OFF: -		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) +		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { +			/* disable the transmitter */  			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); -		else +		} else if (ASIC_IS_DCE4(rdev)) { +			/* disable the transmitter */ +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); +		} else { +			/* disable the encoder and transmitter */  			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); +			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); +			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); +		}  		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {  			if (ASIC_IS_DCE4(rdev))  				atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1740,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	struct drm_encoder *test_encoder; -	struct radeon_encoder_atom_dig *dig; +	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;  	uint32_t dig_enc_in_use = 0; -	/* DCE4/5 */ -	if (ASIC_IS_DCE4(rdev)) { -		dig = radeon_encoder->enc_priv; -		if (ASIC_IS_DCE41(rdev)) { +	if (ASIC_IS_DCE6(rdev)) { +		/* DCE6 */ +		switch (radeon_encoder->encoder_id) { +		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: +			if (dig->linkb) +				return 1; +			else +				return 0; +			break; +		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: +			if (dig->linkb) +				return 3; +			else +				return 2; +			break; +		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: +			if (dig->linkb) +				return 5; +			else +				return 4; +			break; +		} +	} else if (ASIC_IS_DCE4(rdev)) { +		/* DCE4/5 */ +		if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {  			/* ontario follows DCE4 */  			if (rdev->family == CHIP_PALM) {  				if (dig->linkb) @@ -1848,10 +1898,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,  	struct drm_device *dev = encoder->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); -	struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);  	radeon_encoder->pixel_clock = adjusted_mode->clock; +	/* need to call this here rather than in prepare() since we need some crtc info */ +	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); +  	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {  		if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))  			atombios_yuv_setup(encoder, true); @@ -1870,38 +1922,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,  	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:  	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:  	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { -			struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); -			struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - -			if (!connector) -				dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; -			else -				dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - -			/* setup and enable the encoder */ -			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); -			atombios_dig_encoder_setup(encoder, -						   ATOM_ENCODER_CMD_SETUP_PANEL_MODE, -						   dig->panel_mode); -		} else if (ASIC_IS_DCE4(rdev)) { -			/* disable the transmitter */ -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); -			/* setup and enable the encoder */ -			atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - -			/* enable the transmitter */ -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); -		} else { -			/* disable the encoder and transmitter */ -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); -			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - -			/* setup and enable the encoder and transmitter */ -			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); -		} +		/* handled in dpms */  		break;  	case ENCODER_OBJECT_ID_INTERNAL_DDI:  	case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1922,14 +1943,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,  		break;  	} -	if (ext_encoder) { -		if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) -			atombios_external_encoder_setup(encoder, ext_encoder, -							EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); -		else -			atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); -	} -  	atombios_apply_encoder_quirks(encoder, adjusted_mode);  	if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2116,7 +2129,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)  	}  	radeon_atom_output_lock(encoder, true); -	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);  	if (connector) {  		struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2137,6 +2149,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)  static void radeon_atom_encoder_commit(struct drm_encoder *encoder)  { +	/* need to call this here as we need the crtc set up */  	radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);  	radeon_atom_output_lock(encoder, false);  } @@ -2177,14 +2190,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)  	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:  	case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:  	case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -		if (ASIC_IS_DCE4(rdev)) -			/* disable the transmitter */ -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); -		else { -			/* disable the encoder and transmitter */ -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); -			atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); -		} +		/* handled in dpms */  		break;  	case ENCODER_OBJECT_ID_INTERNAL_DDI:  	case ENCODER_OBJECT_ID_INTERNAL_DVO1: diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e585a3b947e..e93b80a6d4e 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1229,24 +1229,8 @@ void evergreen_agp_enable(struct radeon_device *rdev)  void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)  { -	save->vga_control[0] = RREG32(D1VGA_CONTROL); -	save->vga_control[1] = RREG32(D2VGA_CONTROL);  	save->vga_render_control = RREG32(VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); -	save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); -	save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -	if (rdev->num_crtc >= 4) { -		save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); -		save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); -		save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); -		save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); -	} -	if (rdev->num_crtc >= 6) { -		save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); -		save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); -		save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); -		save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); -	}  	/* Stop all video */  	WREG32(VGA_RENDER_CONTROL, 0); @@ -1357,47 +1341,6 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  	/* Unlock host access */  	WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);  	mdelay(1); -	/* Restore video state */ -	WREG32(D1VGA_CONTROL, save->vga_control[0]); -	WREG32(D2VGA_CONTROL, save->vga_control[1]); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); -		WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); -		WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); -	} -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); -	} -	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); -	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); -		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); -	} -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); -	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (rdev->num_crtc >= 4) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); -	} -	if (rdev->num_crtc >= 6) { -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); -		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); -	}  	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);  } @@ -1986,10 +1929,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		rdev->config.evergreen.tile_config |= 1 << 4;  	else { -		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -			rdev->config.evergreen.tile_config |= 1 << 4; -		else +		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +		case 0: /* four banks */  			rdev->config.evergreen.tile_config |= 0 << 4; +			break; +		case 1: /* eight banks */ +			rdev->config.evergreen.tile_config |= 1 << 4; +			break; +		case 2: /* sixteen banks */ +		default: +			rdev->config.evergreen.tile_config |= 2 << 4; +			break; +		}  	}  	rdev->config.evergreen.tile_config |= 0 << 8;  	rdev->config.evergreen.tile_config |= diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index c16554122cc..e44a62a07fe 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -788,6 +788,13 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p,  	case V_030000_SQ_TEX_DIM_1D_ARRAY:  	case V_030000_SQ_TEX_DIM_2D_ARRAY:  		depth = 1; +		break; +	case V_030000_SQ_TEX_DIM_2D_MSAA: +	case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: +		surf.nsamples = 1 << llevel; +		llevel = 0; +		depth = 1; +		break;  	case V_030000_SQ_TEX_DIM_3D:  		break;  	default: @@ -961,13 +968,15 @@ static int evergreen_cs_track_check(struct radeon_cs_parser *p)  	if (track->db_dirty) {  		/* Check stencil buffer */ -		if (G_028800_STENCIL_ENABLE(track->db_depth_control)) { +		if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && +		    G_028800_STENCIL_ENABLE(track->db_depth_control)) {  			r = evergreen_cs_track_validate_stencil(p);  			if (r)  				return r;  		}  		/* Check depth buffer */ -		if (G_028800_Z_ENABLE(track->db_depth_control)) { +		if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && +		    G_028800_Z_ENABLE(track->db_depth_control)) {  			r = evergreen_cs_track_validate_depth(p);  			if (r)  				return r; diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index d3bd098e4e1..79347855d9b 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1277,6 +1277,8 @@  #define   S_028044_FORMAT(x)                           (((x) & 0x1) << 0)  #define   G_028044_FORMAT(x)                           (((x) >> 0) & 0x1)  #define   C_028044_FORMAT                              0xFFFFFFFE +#define	    V_028044_STENCIL_INVALID			0 +#define	    V_028044_STENCIL_8				1  #define   G_028044_TILE_SPLIT(x)                       (((x) >> 8) & 0x7)  #define DB_Z_READ_BASE					0x28048  #define DB_STENCIL_READ_BASE				0x2804c diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 9945d86d900..853800e8582 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -574,10 +574,18 @@ static void cayman_gpu_init(struct radeon_device *rdev)  	if (rdev->flags & RADEON_IS_IGP)  		rdev->config.cayman.tile_config |= 1 << 4;  	else { -		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -			rdev->config.cayman.tile_config |= 1 << 4; -		else +		switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +		case 0: /* four banks */  			rdev->config.cayman.tile_config |= 0 << 4; +			break; +		case 1: /* eight banks */ +			rdev->config.cayman.tile_config |= 1 << 4; +			break; +		case 2: /* sixteen banks */ +		default: +			rdev->config.cayman.tile_config |= 2 << 4; +			break; +		}  	}  	rdev->config.cayman.tile_config |=  		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 637280f541a..d79c639ae73 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3789,3 +3789,23 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)  		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);  	}  } + +/** + * r600_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (R6xx-cayman). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) +{ +	uint64_t clock; + +	mutex_lock(&rdev->gpu_clock_mutex); +	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); +	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | +	        ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); +	mutex_unlock(&rdev->gpu_clock_mutex); +	return clock; +} diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index ca87f7afaf2..f37676d7f21 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -47,18 +47,23 @@ struct r600_cs_track {  	u32			npipes;  	/* value we track */  	u32			sq_config; +	u32			log_nsamples;  	u32			nsamples;  	u32			cb_color_base_last[8];  	struct radeon_bo	*cb_color_bo[8];  	u64			cb_color_bo_mc[8]; -	u32			cb_color_bo_offset[8]; -	struct radeon_bo	*cb_color_frag_bo[8]; /* unused */ -	struct radeon_bo	*cb_color_tile_bo[8]; /* unused */ +	u64			cb_color_bo_offset[8]; +	struct radeon_bo	*cb_color_frag_bo[8]; +	u64			cb_color_frag_offset[8]; +	struct radeon_bo	*cb_color_tile_bo[8]; +	u64			cb_color_tile_offset[8]; +	u32			cb_color_mask[8];  	u32			cb_color_info[8];  	u32			cb_color_view[8];  	u32			cb_color_size_idx[8]; /* unused */  	u32			cb_target_mask;  	u32			cb_shader_mask;  /* unused */ +	bool			is_resolve;  	u32			cb_color_size[8];  	u32			vgt_strmout_en;  	u32			vgt_strmout_buffer_en; @@ -311,7 +316,15 @@ static void r600_cs_track_init(struct r600_cs_track *track)  		track->cb_color_bo[i] = NULL;  		track->cb_color_bo_offset[i] = 0xFFFFFFFF;  		track->cb_color_bo_mc[i] = 0xFFFFFFFF; +		track->cb_color_frag_bo[i] = NULL; +		track->cb_color_frag_offset[i] = 0xFFFFFFFF; +		track->cb_color_tile_bo[i] = NULL; +		track->cb_color_tile_offset[i] = 0xFFFFFFFF; +		track->cb_color_mask[i] = 0xFFFFFFFF;  	} +	track->is_resolve = false; +	track->nsamples = 16; +	track->log_nsamples = 4;  	track->cb_target_mask = 0xFFFFFFFF;  	track->cb_shader_mask = 0xFFFFFFFF;  	track->cb_dirty = true; @@ -348,11 +361,9 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	volatile u32 *ib = p->ib.ptr;  	unsigned array_mode;  	u32 format; +	/* When resolve is used, the second colorbuffer has always 1 sample. */ +	unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples; -	if (G_0280A0_TILE_MODE(track->cb_color_info[i])) { -		dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n"); -		return -EINVAL; -	}  	size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];  	format = G_0280A0_FORMAT(track->cb_color_info[i]);  	if (!r600_fmt_is_valid_color(format)) { @@ -375,7 +386,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	array_check.group_size = track->group_size;  	array_check.nbanks = track->nbanks;  	array_check.npipes = track->npipes; -	array_check.nsamples = track->nsamples; +	array_check.nsamples = nsamples;  	array_check.blocksize = r600_fmt_get_blocksize(format);  	if (r600_get_array_mode_alignment(&array_check,  					  &pitch_align, &height_align, &depth_align, &base_align)) { @@ -420,7 +431,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	}  	/* check offset */ -	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * r600_fmt_get_blocksize(format); +	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * +	      r600_fmt_get_blocksize(format) * nsamples;  	switch (array_mode) {  	default:  	case V_0280A0_ARRAY_LINEAR_GENERAL: @@ -441,7 +453,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  			 * broken userspace.  			 */  		} else { -			dev_warn(p->dev, "%s offset[%d] %d %d %d %lu too big (%d %d) (%d %d %d)\n", +			dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",  				 __func__, i, array_mode,  				 track->cb_color_bo_offset[i], tmp,  				 radeon_bo_size(track->cb_color_bo[i]), @@ -458,6 +470,51 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)  	tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |  		S_028060_SLICE_TILE_MAX(slice_tile_max - 1);  	ib[track->cb_color_size_idx[i]] = tmp; + +	/* FMASK/CMASK */ +	switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { +	case V_0280A0_TILE_DISABLE: +		break; +	case V_0280A0_FRAG_ENABLE: +		if (track->nsamples > 1) { +			uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); +			/* the tile size is 8x8, but the size is in units of bits. +			 * for bytes, do just * 8. */ +			uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1); + +			if (bytes + track->cb_color_frag_offset[i] > +			    radeon_bo_size(track->cb_color_frag_bo[i])) { +				dev_warn(p->dev, "%s FMASK_TILE_MAX too large " +					 "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", +					 __func__, tile_max, bytes, +					 track->cb_color_frag_offset[i], +					 radeon_bo_size(track->cb_color_frag_bo[i])); +				return -EINVAL; +			} +		} +		/* fall through */ +	case V_0280A0_CLEAR_ENABLE: +	{ +		uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); +		/* One block = 128x128 pixels, one 8x8 tile has 4 bits.. +		 * (128*128) / (8*8) / 2 = 128 bytes per block. */ +		uint32_t bytes = (block_max + 1) * 128; + +		if (bytes + track->cb_color_tile_offset[i] > +		    radeon_bo_size(track->cb_color_tile_bo[i])) { +			dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large " +				 "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n", +				 __func__, block_max, bytes, +				 track->cb_color_tile_offset[i], +				 radeon_bo_size(track->cb_color_tile_bo[i])); +			return -EINVAL; +		} +		break; +	} +	default: +		dev_warn(p->dev, "%s invalid tile mode\n", __func__); +		return -EINVAL; +	}  	return 0;  } @@ -566,7 +623,7 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)  		ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;  		nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; -		tmp = ntiles * bpe * 64 * nviews; +		tmp = ntiles * bpe * 64 * nviews * track->nsamples;  		if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {  			dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",  					array_mode, @@ -746,6 +803,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)  	 */  	if (track->cb_dirty) {  		tmp = track->cb_target_mask; + +		/* We must check both colorbuffers for RESOLVE. */ +		if (track->is_resolve) { +			tmp |= 0xff; +		} +  		for (i = 0; i < 8; i++) {  			if ((tmp >> (i * 4)) & 0xF) {  				/* at least one component is enabled */ @@ -764,8 +827,10 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)  	}  	/* Check depth buffer */ -	if (track->db_dirty && (G_028800_STENCIL_ENABLE(track->db_depth_control) || -		G_028800_Z_ENABLE(track->db_depth_control))) { +	if (track->db_dirty && +	    G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID && +	    (G_028800_STENCIL_ENABLE(track->db_depth_control) || +	     G_028800_Z_ENABLE(track->db_depth_control))) {  		r = r600_cs_track_validate_db(p);  		if (r)  			return r; @@ -1229,9 +1294,15 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  		break;  	case R_028C04_PA_SC_AA_CONFIG:  		tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx)); +		track->log_nsamples = tmp;  		track->nsamples = 1 << tmp;  		track->cb_dirty = true;  		break; +	case R_028808_CB_COLOR_CONTROL: +		tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx)); +		track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX; +		track->cb_dirty = true; +		break;  	case R_0280A0_CB_COLOR0_INFO:  	case R_0280A4_CB_COLOR1_INFO:  	case R_0280A8_CB_COLOR2_INFO: @@ -1310,16 +1381,21 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);  				return -EINVAL;  			} -			ib[idx] = track->cb_color_base_last[tmp];  			track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp]; +			track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp]; +			ib[idx] = track->cb_color_base_last[tmp];  		} else {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);  				return -EINVAL;  			} -			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  			track->cb_color_frag_bo[tmp] = reloc->robj; +			track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8; +			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +		} +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true;  		}  		break;  	case R_0280C0_CB_COLOR0_TILE: @@ -1336,16 +1412,35 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)  				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);  				return -EINVAL;  			} -			ib[idx] = track->cb_color_base_last[tmp];  			track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp]; +			track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp]; +			ib[idx] = track->cb_color_base_last[tmp];  		} else {  			r = r600_cs_packet_next_reloc(p, &reloc);  			if (r) {  				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);  				return -EINVAL;  			} -			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);  			track->cb_color_tile_bo[tmp] = reloc->robj; +			track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8; +			ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); +		} +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true; +		} +		break; +	case R_028100_CB_COLOR0_MASK: +	case R_028104_CB_COLOR1_MASK: +	case R_028108_CB_COLOR2_MASK: +	case R_02810C_CB_COLOR3_MASK: +	case R_028110_CB_COLOR4_MASK: +	case R_028114_CB_COLOR5_MASK: +	case R_028118_CB_COLOR6_MASK: +	case R_02811C_CB_COLOR7_MASK: +		tmp = (reg - R_028100_CB_COLOR0_MASK) / 4; +		track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); +		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) { +			track->cb_dirty = true;  		}  		break;  	case CB_COLOR0_BASE: @@ -1490,7 +1585,7 @@ unsigned r600_mip_minify(unsigned size, unsigned level)  }  static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel, -			      unsigned w0, unsigned h0, unsigned d0, unsigned format, +			      unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,  			      unsigned block_align, unsigned height_align, unsigned base_align,  			      unsigned *l0_size, unsigned *mipmap_size)  { @@ -1518,7 +1613,7 @@ static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,  		depth = r600_mip_minify(d0, i); -		size = nbx * nby * blocksize; +		size = nbx * nby * blocksize * nsamples;  		if (nfaces)  			size *= nfaces;  		else @@ -1557,13 +1652,14 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  					      u32 tiling_flags)  {  	struct r600_cs_track *track = p->track; -	u32 nfaces, llevel, blevel, w0, h0, d0; -	u32 word0, word1, l0_size, mipmap_size, word2, word3; +	u32 dim, nfaces, llevel, blevel, w0, h0, d0; +	u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5;  	u32 height_align, pitch, pitch_align, depth_align; -	u32 array, barray, larray; +	u32 barray, larray;  	u64 base_align;  	struct array_mode_checker array_check;  	u32 format; +	bool is_array;  	/* on legacy kernel we don't perform advanced check */  	if (p->rdev == NULL) @@ -1581,12 +1677,28 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);  	}  	word1 = radeon_get_ib_value(p, idx + 1); +	word2 = radeon_get_ib_value(p, idx + 2) << 8; +	word3 = radeon_get_ib_value(p, idx + 3) << 8; +	word4 = radeon_get_ib_value(p, idx + 4); +	word5 = radeon_get_ib_value(p, idx + 5); +	dim = G_038000_DIM(word0);  	w0 = G_038000_TEX_WIDTH(word0) + 1; +	pitch = (G_038000_PITCH(word0) + 1) * 8;  	h0 = G_038004_TEX_HEIGHT(word1) + 1;  	d0 = G_038004_TEX_DEPTH(word1); +	format = G_038004_DATA_FORMAT(word1); +	blevel = G_038010_BASE_LEVEL(word4); +	llevel = G_038014_LAST_LEVEL(word5); +	/* pitch in texels */ +	array_check.array_mode = G_038000_TILE_MODE(word0); +	array_check.group_size = track->group_size; +	array_check.nbanks = track->nbanks; +	array_check.npipes = track->npipes; +	array_check.nsamples = 1; +	array_check.blocksize = r600_fmt_get_blocksize(format);  	nfaces = 1; -	array = 0; -	switch (G_038000_DIM(word0)) { +	is_array = false; +	switch (dim) {  	case V_038000_SQ_TEX_DIM_1D:  	case V_038000_SQ_TEX_DIM_2D:  	case V_038000_SQ_TEX_DIM_3D: @@ -1599,29 +1711,25 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		break;  	case V_038000_SQ_TEX_DIM_1D_ARRAY:  	case V_038000_SQ_TEX_DIM_2D_ARRAY: -		array = 1; +		is_array = true;  		break; -	case V_038000_SQ_TEX_DIM_2D_MSAA:  	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: +		is_array = true; +		/* fall through */ +	case V_038000_SQ_TEX_DIM_2D_MSAA: +		array_check.nsamples = 1 << llevel; +		llevel = 0; +		break;  	default:  		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));  		return -EINVAL;  	} -	format = G_038004_DATA_FORMAT(word1);  	if (!r600_fmt_is_valid_texture(format, p->family)) {  		dev_warn(p->dev, "%s:%d texture invalid format %d\n",  			 __func__, __LINE__, format);  		return -EINVAL;  	} -	/* pitch in texels */ -	pitch = (G_038000_PITCH(word0) + 1) * 8; -	array_check.array_mode = G_038000_TILE_MODE(word0); -	array_check.group_size = track->group_size; -	array_check.nbanks = track->nbanks; -	array_check.npipes = track->npipes; -	array_check.nsamples = 1; -	array_check.blocksize = r600_fmt_get_blocksize(format);  	if (r600_get_array_mode_alignment(&array_check,  					  &pitch_align, &height_align, &depth_align, &base_align)) {  		dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n", @@ -1647,24 +1755,17 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		return -EINVAL;  	} -	word2 = radeon_get_ib_value(p, idx + 2) << 8; -	word3 = radeon_get_ib_value(p, idx + 3) << 8; - -	word0 = radeon_get_ib_value(p, idx + 4); -	word1 = radeon_get_ib_value(p, idx + 5); -	blevel = G_038010_BASE_LEVEL(word0); -	llevel = G_038014_LAST_LEVEL(word1);  	if (blevel > llevel) {  		dev_warn(p->dev, "texture blevel %d > llevel %d\n",  			 blevel, llevel);  	} -	if (array == 1) { -		barray = G_038014_BASE_ARRAY(word1); -		larray = G_038014_LAST_ARRAY(word1); +	if (is_array) { +		barray = G_038014_BASE_ARRAY(word5); +		larray = G_038014_LAST_ARRAY(word5);  		nfaces = larray - barray + 1;  	} -	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format, +	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,  			  pitch_align, height_align, base_align,  			  &l0_size, &mipmap_size);  	/* using get ib will give us the offset into the texture bo */ @@ -1677,7 +1778,6 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,  		return -EINVAL;  	}  	/* using get ib will give us the offset into the mipmap bo */ -	word3 = radeon_get_ib_value(p, idx + 3) << 8;  	if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {  		/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",  		  w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/ diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 4b116ae75fc..fa6f37099ba 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -66,6 +66,14 @@  #define	CC_RB_BACKEND_DISABLE				0x98F4  #define		BACKEND_DISABLE(x)				((x) << 16) +#define R_028808_CB_COLOR_CONTROL			0x28808 +#define   S_028808_SPECIAL_OP(x)                       (((x) & 0x7) << 4) +#define   G_028808_SPECIAL_OP(x)                       (((x) >> 4) & 0x7) +#define   C_028808_SPECIAL_OP                          0xFFFFFF8F +#define     V_028808_SPECIAL_NORMAL                     0x00 +#define     V_028808_SPECIAL_DISABLE                    0x01 +#define     V_028808_SPECIAL_RESOLVE_BOX                0x07 +  #define	CB_COLOR0_BASE					0x28040  #define	CB_COLOR1_BASE					0x28044  #define	CB_COLOR2_BASE					0x28048 @@ -92,6 +100,20 @@  #define R_028094_CB_COLOR5_VIEW                      0x028094  #define R_028098_CB_COLOR6_VIEW                      0x028098  #define R_02809C_CB_COLOR7_VIEW                      0x02809C +#define R_028100_CB_COLOR0_MASK                      0x028100 +#define   S_028100_CMASK_BLOCK_MAX(x)                  (((x) & 0xFFF) << 0) +#define   G_028100_CMASK_BLOCK_MAX(x)                  (((x) >> 0) & 0xFFF) +#define   C_028100_CMASK_BLOCK_MAX                     0xFFFFF000 +#define   S_028100_FMASK_TILE_MAX(x)                   (((x) & 0xFFFFF) << 12) +#define   G_028100_FMASK_TILE_MAX(x)                   (((x) >> 12) & 0xFFFFF) +#define   C_028100_FMASK_TILE_MAX                      0x00000FFF +#define R_028104_CB_COLOR1_MASK                      0x028104 +#define R_028108_CB_COLOR2_MASK                      0x028108 +#define R_02810C_CB_COLOR3_MASK                      0x02810C +#define R_028110_CB_COLOR4_MASK                      0x028110 +#define R_028114_CB_COLOR5_MASK                      0x028114 +#define R_028118_CB_COLOR6_MASK                      0x028118 +#define R_02811C_CB_COLOR7_MASK                      0x02811C  #define CB_COLOR0_INFO                                  0x280a0  #	define CB_FORMAT(x)				((x) << 2)  #       define CB_ARRAY_MODE(x)                         ((x) << 8) @@ -602,6 +624,9 @@  #define RLC_HB_WPTR                                       0x3f1c  #define RLC_HB_WPTR_LSB_ADDR                              0x3f14  #define RLC_HB_WPTR_MSB_ADDR                              0x3f18 +#define RLC_GPU_CLOCK_COUNT_LSB				  0x3f38 +#define RLC_GPU_CLOCK_COUNT_MSB				  0x3f3c +#define RLC_CAPTURE_GPU_CLOCK_COUNT			  0x3f40  #define RLC_MC_CNTL                                       0x3f44  #define RLC_UCODE_CNTL                                    0x3f48  #define RLC_UCODE_ADDR                                    0x3f2c @@ -1397,6 +1422,9 @@  #define   S_0280A0_TILE_MODE(x)                        (((x) & 0x3) << 18)  #define   G_0280A0_TILE_MODE(x)                        (((x) >> 18) & 0x3)  #define   C_0280A0_TILE_MODE                           0xFFF3FFFF +#define     V_0280A0_TILE_DISABLE			0 +#define     V_0280A0_CLEAR_ENABLE			1 +#define     V_0280A0_FRAG_ENABLE			2  #define   S_0280A0_BLEND_CLAMP(x)                      (((x) & 0x1) << 20)  #define   G_0280A0_BLEND_CLAMP(x)                      (((x) >> 20) & 0x1)  #define   C_0280A0_BLEND_CLAMP                         0xFFEFFFFF diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 5431af29240..59a15315ae9 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -142,21 +142,6 @@ struct radeon_device;  /*   * BIOS.   */ -#define ATRM_BIOS_PAGE 4096 - -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_atrm_supported(struct pci_dev *pdev); -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); -#else -static inline bool radeon_atrm_supported(struct pci_dev *pdev) -{ -	return false; -} - -static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ -	return -EINVAL; -} -#endif  bool radeon_get_bios(struct radeon_device *rdev);  /* @@ -300,6 +285,7 @@ struct radeon_bo_va {  	uint64_t			soffset;  	uint64_t			eoffset;  	uint32_t			flags; +	struct radeon_fence		*fence;  	bool				valid;  }; @@ -1533,6 +1519,7 @@ struct radeon_device {  	unsigned 		debugfs_count;  	/* virtual memory */  	struct radeon_vm_manager	vm_manager; +	struct mutex			gpu_clock_mutex;  };  int radeon_device_init(struct radeon_device *rdev, @@ -1733,11 +1720,11 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v);  #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev))  #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev))  #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pflip.pre_page_flip((rdev), (crtc)) -#define radeon_page_flip(rdev, crtc, base) rdev->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) rdev->asic->pflip.post_page_flip((rdev), (crtc)) -#define radeon_wait_for_vblank(rdev, crtc) rdev->asic->display.wait_for_vblank((rdev), (crtc)) -#define radeon_mc_wait_for_idle(rdev) rdev->asic->mc_wait_for_idle((rdev)) +#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) +#define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) +#define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))  /* Common functions */  /* AGP */ diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index f4af2431043..18c38d14c8c 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -255,13 +255,10 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev);   * rv515   */  struct rv515_mc_save { -	u32 d1vga_control; -	u32 d2vga_control;  	u32 vga_render_control;  	u32 vga_hdp_control; -	u32 d1crtc_control; -	u32 d2crtc_control;  }; +  int rv515_init(struct radeon_device *rdev);  void rv515_fini(struct radeon_device *rdev);  uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -371,6 +368,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev,  			unsigned num_gpu_pages,  			struct radeon_sa_bo *vb);  int r600_mc_wait_for_idle(struct radeon_device *rdev); +uint64_t r600_get_gpu_clock(struct radeon_device *rdev);  /*   * rv770,rv730,rv710,rv740 @@ -389,11 +387,10 @@ void r700_cp_fini(struct radeon_device *rdev);   * evergreen   */  struct evergreen_mc_save { -	u32 vga_control[6];  	u32 vga_render_control;  	u32 vga_hdp_control; -	u32 crtc_control[6];  }; +  void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);  int evergreen_init(struct radeon_device *rdev);  void evergreen_fini(struct radeon_device *rdev); @@ -472,5 +469,6 @@ int si_vm_bind(struct radeon_device *rdev, struct radeon_vm *vm, int id);  void si_vm_unbind(struct radeon_device *rdev, struct radeon_vm *vm);  void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm);  int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +uint64_t si_get_gpu_clock(struct radeon_device *rdev);  #endif diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b1e3820df36..d67d4f3eb6f 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,  	}  	/* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ -	if ((dev->pdev->device == 0x9802) && +	if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) &&  	    (dev->pdev->subsystem_vendor == 0x1734) &&  	    (dev->pdev->subsystem_device == 0x11bd)) {  		if (*connector_type == DRM_MODE_CONNECTOR_VGA) { @@ -1263,6 +1263,8 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)  union igp_info {  	struct _ATOM_INTEGRATED_SYSTEM_INFO info;  	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; +	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; +	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;  };  bool radeon_atombios_sideport_present(struct radeon_device *rdev) @@ -1390,27 +1392,50 @@ static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev,  	struct radeon_mode_info *mode_info = &rdev->mode_info;  	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);  	u16 data_offset, size; -	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; +	union igp_info *igp_info;  	u8 frev, crev;  	u16 percentage = 0, rate = 0;  	/* get any igp specific overrides */  	if (atom_parse_data_header(mode_info->atom_context, index, &size,  				   &frev, &crev, &data_offset)) { -		igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) +		igp_info = (union igp_info *)  			(mode_info->atom_context->bios + data_offset); -		switch (id) { -		case ASIC_INTERNAL_SS_ON_TMDS: -			percentage = le16_to_cpu(igp_info->usDVISSPercentage); -			rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); +		switch (crev) { +		case 6: +			switch (id) { +			case ASIC_INTERNAL_SS_ON_TMDS: +				percentage = le16_to_cpu(igp_info->info_6.usDVISSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usDVISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_HDMI: +				percentage = le16_to_cpu(igp_info->info_6.usHDMISSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usHDMISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_LVDS: +				percentage = le16_to_cpu(igp_info->info_6.usLvdsSSPercentage); +				rate = le16_to_cpu(igp_info->info_6.usLvdsSSpreadRateIn10Hz); +				break; +			}  			break; -		case ASIC_INTERNAL_SS_ON_HDMI: -			percentage = le16_to_cpu(igp_info->usHDMISSPercentage); -			rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); +		case 7: +			switch (id) { +			case ASIC_INTERNAL_SS_ON_TMDS: +				percentage = le16_to_cpu(igp_info->info_7.usDVISSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usDVISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_HDMI: +				percentage = le16_to_cpu(igp_info->info_7.usHDMISSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usHDMISSpreadRateIn10Hz); +				break; +			case ASIC_INTERNAL_SS_ON_LVDS: +				percentage = le16_to_cpu(igp_info->info_7.usLvdsSSPercentage); +				rate = le16_to_cpu(igp_info->info_7.usLvdsSSpreadRateIn10Hz); +				break; +			}  			break; -		case ASIC_INTERNAL_SS_ON_LVDS: -			percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); -			rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); +		default: +			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);  			break;  		}  		if (percentage) diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fcb008..2a2cf0b88a2 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,57 +30,8 @@ static struct radeon_atpx_priv {  	/* handle for device - and atpx */  	acpi_handle dhandle;  	acpi_handle atpx_handle; -	acpi_handle atrm_handle;  } radeon_atpx_priv; -/* retrieve the ROM in 4k blocks */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, -			    int offset, int len) -{ -	acpi_status status; -	union acpi_object atrm_arg_elements[2], *obj; -	struct acpi_object_list atrm_arg; -	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - -	atrm_arg.count = 2; -	atrm_arg.pointer = &atrm_arg_elements[0]; - -	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; -	atrm_arg_elements[0].integer.value = offset; - -	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; -	atrm_arg_elements[1].integer.value = len; - -	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); -	if (ACPI_FAILURE(status)) { -		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); -		return -ENODEV; -	} - -	obj = (union acpi_object *)buffer.pointer; -	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); -	len = obj->buffer.length; -	kfree(buffer.pointer); -	return len; -} - -bool radeon_atrm_supported(struct pci_dev *pdev) -{ -	/* get the discrete ROM only via ATRM */ -	if (!radeon_atpx_priv.atpx_detected) -		return false; - -	if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) -		return false; -	return true; -} - - -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) -{ -	return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); -} -  static int radeon_atpx_get_version(acpi_handle handle)  {  	acpi_status status; @@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,  static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)  { -	acpi_handle dhandle, atpx_handle, atrm_handle; +	acpi_handle dhandle, atpx_handle;  	acpi_status status;  	dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)  	if (ACPI_FAILURE(status))  		return false; -	status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); -	if (ACPI_FAILURE(status)) -		return false; -  	radeon_atpx_priv.dhandle = dhandle;  	radeon_atpx_priv.atpx_handle = atpx_handle; -	radeon_atpx_priv.atrm_handle = atrm_handle;  	return true;  } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f4881e5a..d306cc8fdea 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@  #include <linux/vga_switcheroo.h>  #include <linux/slab.h> +#include <linux/acpi.h>  /*   * BIOS.   */ @@ -98,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev)  	return true;  } +#ifdef CONFIG_ACPI  /* ATRM is used to get the BIOS on the discrete cards in   * dual-gpu systems.   */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, +			    int offset, int len) +{ +	acpi_status status; +	union acpi_object atrm_arg_elements[2], *obj; +	struct acpi_object_list atrm_arg; +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + +	atrm_arg.count = 2; +	atrm_arg.pointer = &atrm_arg_elements[0]; + +	atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; +	atrm_arg_elements[0].integer.value = offset; + +	atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; +	atrm_arg_elements[1].integer.value = len; + +	status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); +	if (ACPI_FAILURE(status)) { +		printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); +		return -ENODEV; +	} + +	obj = (union acpi_object *)buffer.pointer; +	memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); +	len = obj->buffer.length; +	kfree(buffer.pointer); +	return len; +} +  static bool radeon_atrm_get_bios(struct radeon_device *rdev)  {  	int ret;  	int size = 256 * 1024;  	int i; +	struct pci_dev *pdev = NULL; +	acpi_handle dhandle, atrm_handle; +	acpi_status status; +	bool found = false; + +	/* ATRM is for the discrete card only */ +	if (rdev->flags & RADEON_IS_IGP) +		return false; -	if (!radeon_atrm_supported(rdev->pdev)) +	while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { +		dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); +		if (!dhandle) +			continue; + +		status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); +		if (!ACPI_FAILURE(status)) { +			found = true; +			break; +		} +	} + +	if (!found)  		return false;  	rdev->bios = kmalloc(size, GFP_KERNEL); @@ -117,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)  	}  	for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { -		ret = radeon_atrm_get_bios_chunk(rdev->bios, -						 (i * ATRM_BIOS_PAGE), -						 ATRM_BIOS_PAGE); +		ret = radeon_atrm_call(atrm_handle, +				       rdev->bios, +				       (i * ATRM_BIOS_PAGE), +				       ATRM_BIOS_PAGE);  		if (ret < ATRM_BIOS_PAGE)  			break;  	} @@ -130,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)  	}  	return true;  } +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ +	return false; +} +#endif  static bool ni_read_disabled_bios(struct radeon_device *rdev)  { @@ -476,6 +549,61 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev)  		return legacy_read_disabled_bios(rdev);  } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ +	bool ret = false; +	struct acpi_table_header *hdr; +	acpi_size tbl_size; +	UEFI_ACPI_VFCT *vfct; +	GOP_VBIOS_CONTENT *vbios; +	VFCT_IMAGE_HEADER *vhdr; + +	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) +		return false; +	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { +		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); +		goto out_unmap; +	} + +	vfct = (UEFI_ACPI_VFCT *)hdr; +	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { +		DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); +		goto out_unmap; +	} + +	vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); +	vhdr = &vbios->VbiosHeader; +	DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", +			vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, +			vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + +	if (vhdr->PCIBus != rdev->pdev->bus->number || +	    vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || +	    vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || +	    vhdr->VendorID != rdev->pdev->vendor || +	    vhdr->DeviceID != rdev->pdev->device) { +		DRM_INFO("ACPI VFCT table is not for this card\n"); +		goto out_unmap; +	}; + +	if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { +		DRM_ERROR("ACPI VFCT image truncated\n"); +		goto out_unmap; +	} + +	rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); +	ret = !!rdev->bios; + +out_unmap: +	return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ +	return false; +} +#endif  bool radeon_get_bios(struct radeon_device *rdev)  { @@ -484,6 +612,8 @@ bool radeon_get_bios(struct radeon_device *rdev)  	r = radeon_atrm_get_bios(rdev);  	if (r == false) +		r = radeon_acpi_vfct_bios(rdev); +	if (r == false)  		r = igp_read_bios_from_vram(rdev);  	if (r == false)  		r = radeon_read_bios(rdev); diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 576f4f6919f..f75247d42ff 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -719,6 +719,34 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde  	return i2c;  } +static struct radeon_i2c_bus_rec radeon_combios_get_i2c_info_from_table(struct radeon_device *rdev) +{ +	struct drm_device *dev = rdev->ddev; +	struct radeon_i2c_bus_rec i2c; +	u16 offset; +	u8 id, blocks, clk, data; +	int i; + +	i2c.valid = false; + +	offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); +	if (offset) { +		blocks = RBIOS8(offset + 2); +		for (i = 0; i < blocks; i++) { +			id = RBIOS8(offset + 3 + (i * 5) + 0); +			if (id == 136) { +				clk = RBIOS8(offset + 3 + (i * 5) + 3); +				data = RBIOS8(offset + 3 + (i * 5) + 4); +				/* gpiopad */ +				i2c = combios_setup_i2c_bus(rdev, DDC_MONID, +							    (1 << clk), (1 << data)); +				break; +			} +		} +	} +	return i2c; +} +  void radeon_combios_i2c_init(struct radeon_device *rdev)  {  	struct drm_device *dev = rdev->ddev; @@ -755,30 +783,14 @@ void radeon_combios_i2c_init(struct radeon_device *rdev)  	} else if (rdev->family == CHIP_RS300 ||  		   rdev->family == CHIP_RS400 ||  		   rdev->family == CHIP_RS480) { -		u16 offset; -		u8 id, blocks, clk, data; -		int i; -  		/* 0x68 */  		i2c = combios_setup_i2c_bus(rdev, DDC_CRT2, 0, 0);  		rdev->i2c_bus[3] = radeon_i2c_create(dev, &i2c, "MONID"); -		offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE); -		if (offset) { -			blocks = RBIOS8(offset + 2); -			for (i = 0; i < blocks; i++) { -				id = RBIOS8(offset + 3 + (i * 5) + 0); -				if (id == 136) { -					clk = RBIOS8(offset + 3 + (i * 5) + 3); -					data = RBIOS8(offset + 3 + (i * 5) + 4); -					/* gpiopad */ -					i2c = combios_setup_i2c_bus(rdev, DDC_MONID, -								    (1 << clk), (1 << data)); -					rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK"); -					break; -				} -			} -		} +		/* gpiopad */ +		i2c = radeon_combios_get_i2c_info_from_table(rdev); +		if (i2c.valid) +			rdev->i2c_bus[4] = radeon_i2c_create(dev, &i2c, "GPIOPAD_MASK");  	} else if ((rdev->family == CHIP_R200) ||  		   (rdev->family >= CHIP_R300)) {  		/* 0x68 */ @@ -2321,7 +2333,10 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)  			connector = (tmp >> 12) & 0xf;  			ddc_type = (tmp >> 8) & 0xf; -			ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0); +			if (ddc_type == 5) +				ddc_i2c = radeon_combios_get_i2c_info_from_table(rdev); +			else +				ddc_i2c = combios_setup_i2c_bus(rdev, ddc_type, 0, 0);  			switch (connector) {  			case CONNECTOR_PROPRIETARY_LEGACY: diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 8a4c49ef0cc..b4a0db24f4d 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -278,6 +278,30 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)  	return 0;  } +static void radeon_bo_vm_fence_va(struct radeon_cs_parser *parser, +				  struct radeon_fence *fence) +{ +	struct radeon_fpriv *fpriv = parser->filp->driver_priv; +	struct radeon_vm *vm = &fpriv->vm; +	struct radeon_bo_list *lobj; + +	if (parser->chunk_ib_idx == -1) { +		return; +	} +	if ((parser->cs_flags & RADEON_CS_USE_VM) == 0) { +		return; +	} + +	list_for_each_entry(lobj, &parser->validated, tv.head) { +		struct radeon_bo_va *bo_va; +		struct radeon_bo *rbo = lobj->bo; + +		bo_va = radeon_bo_va(rbo, vm); +		radeon_fence_unref(&bo_va->fence); +		bo_va->fence = radeon_fence_ref(fence); +	} +} +  /**   * cs_parser_fini() - clean parser states   * @parser:	parser structure holding parsing context. @@ -290,11 +314,14 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)  {  	unsigned i; -	if (!error) +	if (!error) { +		/* fence all bo va before ttm_eu_fence_buffer_objects so bo are still reserved */ +		radeon_bo_vm_fence_va(parser, parser->ib.fence);  		ttm_eu_fence_buffer_objects(&parser->validated,  					    parser->ib.fence); -	else +	} else {  		ttm_eu_backoff_reservation(&parser->validated); +	}  	if (parser->relocs != NULL) {  		for (i = 0; i < parser->nrelocs; i++) { @@ -388,7 +415,6 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,  	if (parser->chunk_ib_idx == -1)  		return 0; -  	if ((parser->cs_flags & RADEON_CS_USE_VM) == 0)  		return 0; diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 711e95ad39b..8794744cdf1 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -67,7 +67,8 @@ static void radeon_hide_cursor(struct drm_crtc *crtc)  	if (ASIC_IS_DCE4(rdev)) {  		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); -		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); +		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | +		       EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));  	} else if (ASIC_IS_AVIVO(rdev)) {  		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); @@ -94,7 +95,8 @@ static void radeon_show_cursor(struct drm_crtc *crtc)  	if (ASIC_IS_DCE4(rdev)) {  		WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | -		       EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); +		       EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | +		       EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));  	} else if (ASIC_IS_AVIVO(rdev)) {  		WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);  		WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 742af8244e8..7a3daebd732 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1009,6 +1009,7 @@ int radeon_device_init(struct radeon_device *rdev,  	atomic_set(&rdev->ih.lock, 0);  	mutex_init(&rdev->gem.mutex);  	mutex_init(&rdev->pm.mutex); +	mutex_init(&rdev->gpu_clock_mutex);  	init_rwsem(&rdev->pm.mclk_lock);  	init_rwsem(&rdev->exclusive_lock);  	init_waitqueue_head(&rdev->irq.vblank_queue); @@ -1050,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev,  	if (rdev->flags & RADEON_IS_AGP)  		rdev->need_dma32 = true;  	if ((rdev->flags & RADEON_IS_PCI) && -	    (rdev->family < CHIP_RS400)) +	    (rdev->family <= CHIP_RS740))  		rdev->need_dma32 = true;  	dma_bits = rdev->need_dma32 ? 32 : 40; @@ -1345,12 +1346,15 @@ retry:  		for (i = 0; i < RADEON_NUM_RINGS; ++i) {  			radeon_ring_restore(rdev, &rdev->ring[i],  					    ring_sizes[i], ring_data[i]); +			ring_sizes[i] = 0; +			ring_data[i] = NULL;  		}  		r = radeon_ib_ring_tests(rdev);  		if (r) {  			dev_err(rdev->dev, "ib ring test failed (%d).\n", r);  			if (saved) { +				saved = false;  				radeon_suspend(rdev);  				goto retry;  			} diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dcea6f01ae4..8c593ea82c4 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -59,9 +59,14 @@   *   2.15.0 - add max_pipes query   *   2.16.0 - fix evergreen 2D tiled surface calculation   *   2.17.0 - add STRMOUT_BASE_UPDATE for r7xx + *   2.18.0 - r600-eg: allow "invalid" DB formats + *   2.19.0 - r600-eg: MSAA textures + *   2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query + *   2.21.0 - r600-r700: FMASK and CMASK + *   2.22.0 - r600 only: RESOLVE_BOX allowed   */  #define KMS_DRIVER_MAJOR	2 -#define KMS_DRIVER_MINOR	17 +#define KMS_DRIVER_MINOR	22  #define KMS_DRIVER_PATCHLEVEL	0  int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);  int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7b737b9339a..2a59375dbe5 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev,   */  void radeon_fence_process(struct radeon_device *rdev, int ring)  { -	uint64_t seq, last_seq; +	uint64_t seq, last_seq, last_emitted;  	unsigned count_loop = 0;  	bool wake = false; @@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring)  	 */  	last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);  	do { +		last_emitted = rdev->fence_drv[ring].sync_seq[ring];  		seq = radeon_fence_read(rdev, ring);  		seq |= last_seq & 0xffffffff00000000LL;  		if (seq < last_seq) { -			seq += 0x100000000LL; +			seq &= 0xffffffff; +			seq |= last_emitted & 0xffffffff00000000LL;  		} -		if (seq == last_seq) { +		if (seq <= last_seq || seq > last_emitted) {  			break;  		}  		/* If we loop over we don't want to return without diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index b3720054614..bb3b7fe05cc 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -814,7 +814,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,  		return -EINVAL;  	} -	if (bo_va->valid) +	if (bo_va->valid && mem)  		return 0;  	ngpu_pages = radeon_bo_ngpu_pages(bo); @@ -859,11 +859,27 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev,  		     struct radeon_bo *bo)  {  	struct radeon_bo_va *bo_va; +	int r;  	bo_va = radeon_bo_va(bo, vm);  	if (bo_va == NULL)  		return 0; +	/* wait for va use to end */ +	while (bo_va->fence) { +		r = radeon_fence_wait(bo_va->fence, false); +		if (r) { +			DRM_ERROR("error while waiting for fence: %d\n", r); +		} +		if (r == -EDEADLK) { +			r = radeon_gpu_reset(rdev); +			if (!r) +				continue; +		} +		break; +	} +	radeon_fence_unref(&bo_va->fence); +  	mutex_lock(&rdev->vm_manager.lock);  	mutex_lock(&vm->mutex);  	radeon_vm_bo_update_pte(rdev, vm, bo, NULL); @@ -934,7 +950,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)  }  /** - * radeon_vm_init - tear down a vm instance + * radeon_vm_fini - tear down a vm instance   *   * @rdev: radeon_device pointer   * @vm: requested vm @@ -952,12 +968,15 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)  	radeon_vm_unbind_locked(rdev, vm);  	mutex_unlock(&rdev->vm_manager.lock); -	/* remove all bo */ +	/* remove all bo at this point non are busy any more because unbind +	 * waited for the last vm fence to signal +	 */  	r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);  	if (!r) {  		bo_va = radeon_bo_va(rdev->ring_tmp_bo.bo, vm);  		list_del_init(&bo_va->bo_list);  		list_del_init(&bo_va->vm_list); +		radeon_fence_unref(&bo_va->fence);  		radeon_bo_unreserve(rdev->ring_tmp_bo.bo);  		kfree(bo_va);  	} @@ -969,6 +988,7 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)  		r = radeon_bo_reserve(bo_va->bo, false);  		if (!r) {  			list_del_init(&bo_va->bo_list); +			radeon_fence_unref(&bo_va->fence);  			radeon_bo_unreserve(bo_va->bo);  			kfree(bo_va);  		} diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 84d04524573..1b57b0058ad 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -134,25 +134,16 @@ void radeon_gem_object_close(struct drm_gem_object *obj,  	struct radeon_device *rdev = rbo->rdev;  	struct radeon_fpriv *fpriv = file_priv->driver_priv;  	struct radeon_vm *vm = &fpriv->vm; -	struct radeon_bo_va *bo_va, *tmp;  	if (rdev->family < CHIP_CAYMAN) {  		return;  	}  	if (radeon_bo_reserve(rbo, false)) { +		dev_err(rdev->dev, "leaking bo va because we fail to reserve bo\n");  		return;  	} -	list_for_each_entry_safe(bo_va, tmp, &rbo->va, bo_list) { -		if (bo_va->vm == vm) { -			/* remove from this vm address space */ -			mutex_lock(&vm->mutex); -			list_del(&bo_va->vm_list); -			mutex_unlock(&vm->mutex); -			list_del(&bo_va->bo_list); -			kfree(bo_va); -		} -	} +	radeon_vm_bo_rmv(rdev, vm, rbo);  	radeon_bo_unreserve(rbo);  } diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 1d73f16b5d9..414b4acf694 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -29,6 +29,7 @@  #include "drm_sarea.h"  #include "radeon.h"  #include "radeon_drm.h" +#include "radeon_asic.h"  #include <linux/vga_switcheroo.h>  #include <linux/slab.h> @@ -167,17 +168,39 @@ static void radeon_set_filp_rights(struct drm_device *dev,  int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  {  	struct radeon_device *rdev = dev->dev_private; -	struct drm_radeon_info *info; +	struct drm_radeon_info *info = data;  	struct radeon_mode_info *minfo = &rdev->mode_info; -	uint32_t *value_ptr; -	uint32_t value; +	uint32_t value, *value_ptr; +	uint64_t value64, *value_ptr64;  	struct drm_crtc *crtc;  	int i, found; -	info = data; +	/* TIMESTAMP is a 64-bit value, needs special handling. */ +	if (info->request == RADEON_INFO_TIMESTAMP) { +		if (rdev->family >= CHIP_R600) { +			value_ptr64 = (uint64_t*)((unsigned long)info->value); +			if (rdev->family >= CHIP_TAHITI) { +				value64 = si_get_gpu_clock(rdev); +			} else { +				value64 = r600_get_gpu_clock(rdev); +			} + +			if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { +				DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); +				return -EFAULT; +			} +			return 0; +		} else { +			DRM_DEBUG_KMS("timestamp is r6xx+ only!\n"); +			return -EINVAL; +		} +	} +  	value_ptr = (uint32_t *)((unsigned long)info->value); -	if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) +	if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { +		DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);  		return -EFAULT; +	}  	switch (info->request) {  	case RADEON_INFO_DEVICE_ID: @@ -337,7 +360,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)  		return -EINVAL;  	}  	if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { -		DRM_ERROR("copy_to_user\n"); +		DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);  		return -EFAULT;  	}  	return 0; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index d5fd615897e..94b4a1c1289 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,  static void radeon_crtc_prepare(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct drm_crtc *crtci; +	radeon_crtc->in_mode_set = true;  	/*  	* The hardware wedges sometimes if you reconfigure one CRTC  	* whilst another is running (see fdo bug #24611). @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc)  static void radeon_crtc_commit(struct drm_crtc *crtc)  { +	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct drm_crtc *crtci; @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)  		if (crtci->enabled)  			radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);  	} +	radeon_crtc->in_mode_set = false;  }  static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f380d59c576..d56978949f3 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -275,6 +275,7 @@ struct radeon_crtc {  	u16 lut_r[256], lut_g[256], lut_b[256];  	bool enabled;  	bool can_tile; +	bool in_mode_set;  	uint32_t crtc_offset;  	struct drm_gem_object *cursor_bo;  	uint64_t cursor_addr; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 1f1a4c803c1..9024e722283 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -52,11 +52,7 @@ void radeon_bo_clear_va(struct radeon_bo *bo)  	list_for_each_entry_safe(bo_va, tmp, &bo->va, bo_list) {  		/* remove from all vm address space */ -		mutex_lock(&bo_va->vm->mutex); -		list_del(&bo_va->vm_list); -		mutex_unlock(&bo_va->vm->mutex); -		list_del(&bo_va->bo_list); -		kfree(bo_va); +		radeon_vm_bo_rmv(bo->rdev, bo_va->vm, bo);  	}  } @@ -136,6 +132,7 @@ int radeon_bo_create(struct radeon_device *rdev,  	acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,  				       sizeof(struct radeon_bo)); +retry:  	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);  	if (bo == NULL)  		return -ENOMEM; @@ -149,8 +146,6 @@ int radeon_bo_create(struct radeon_device *rdev,  	bo->surface_reg = -1;  	INIT_LIST_HEAD(&bo->list);  	INIT_LIST_HEAD(&bo->va); - -retry:  	radeon_ttm_placement_from_domain(bo, domain);  	/* Kernel allocation are uninterruptible */  	down_read(&rdev->pm.mclk_lock); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index ec79b375043..43c431a2686 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -706,6 +706,7 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig  	if (radeon_debugfs_ring_init(rdev, ring)) {  		DRM_ERROR("Failed to register debugfs file for rings !\n");  	} +	radeon_ring_lockup_update(ring);  	return 0;  } diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 5e659b034d9..20bfbda7b3f 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -744,15 +744,6 @@ r600 0x9400  0x00028C38 CB_CLRCMP_DST  0x00028C3C CB_CLRCMP_MSK  0x00028C34 CB_CLRCMP_SRC -0x00028100 CB_COLOR0_MASK -0x00028104 CB_COLOR1_MASK -0x00028108 CB_COLOR2_MASK -0x0002810C CB_COLOR3_MASK -0x00028110 CB_COLOR4_MASK -0x00028114 CB_COLOR5_MASK -0x00028118 CB_COLOR6_MASK -0x0002811C CB_COLOR7_MASK -0x00028808 CB_COLOR_CONTROL  0x0002842C CB_FOG_BLUE  0x00028428 CB_FOG_GREEN  0x00028424 CB_FOG_RED diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index a12fbcc8ccb..aa8ef491ef3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)  void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)  { -	save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); -	save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL);  	save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); -	save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); -	save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL);  	/* Stop all video */  	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)  	/* Unlock host access */  	WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);  	mdelay(1); -	/* Restore video state */ -	WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); -	WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); -	WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); -	WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);  	WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);  } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c053f819377..0139e227e3c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1639,11 +1639,19 @@ static void si_gpu_init(struct radeon_device *rdev)  		/* XXX what about 12? */  		rdev->config.si.tile_config |= (3 << 0);  		break; -	} -	if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) -		rdev->config.si.tile_config |= 1 << 4; -	else +	}	 +	switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { +	case 0: /* four banks */  		rdev->config.si.tile_config |= 0 << 4; +		break; +	case 1: /* eight banks */ +		rdev->config.si.tile_config |= 1 << 4; +		break; +	case 2: /* sixteen banks */ +	default: +		rdev->config.si.tile_config |= 2 << 4; +		break; +	}  	rdev->config.si.tile_config |=  		((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;  	rdev->config.si.tile_config |= @@ -3960,3 +3968,22 @@ void si_fini(struct radeon_device *rdev)  	rdev->bios = NULL;  } +/** + * si_get_gpu_clock - return GPU clock counter snapshot + * + * @rdev: radeon_device pointer + * + * Fetches a GPU clock counter snapshot (SI). + * Returns the 64 bit clock counter snapshot. + */ +uint64_t si_get_gpu_clock(struct radeon_device *rdev) +{ +	uint64_t clock; + +	mutex_lock(&rdev->gpu_clock_mutex); +	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); +	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | +	        ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); +	mutex_unlock(&rdev->gpu_clock_mutex); +	return clock; +} diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7869089e876..ef4815c27b1 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -698,6 +698,9 @@  #define RLC_UCODE_ADDR                                    0xC32C  #define RLC_UCODE_DATA                                    0xC330 +#define RLC_GPU_CLOCK_COUNT_LSB                           0xC338 +#define RLC_GPU_CLOCK_COUNT_MSB                           0xC33C +#define RLC_CAPTURE_GPU_CLOCK_COUNT                       0xC340  #define RLC_MC_CNTL                                       0xC344  #define RLC_UCODE_CNTL                                    0xC348 diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index d31d4cca9a4..c5a164337bd 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 7f119870147..867dc03000e 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 90f6b13acfa..a7f4d6bd133 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig index 0b5e096d39a..56e0bf31d42 100644 --- a/drivers/gpu/drm/udl/Kconfig +++ b/drivers/gpu/drm/udl/Kconfig @@ -1,6 +1,7 @@  config DRM_UDL  	tristate "DisplayLink"  	depends on DRM && EXPERIMENTAL +	depends on USB_ARCH_HAS_HCD  	select DRM_USB  	select FB_SYS_FILLRECT  	select FB_SYS_COPYAREA diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 6e52069894b..9f84128505b 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = {  	.unlocked_ioctl	= drm_ioctl,  	.release = drm_release,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 7bd65bdd15a..291ecc14558 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -308,7 +308,7 @@ struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,  	/* need to attach */  	attach = dma_buf_attach(dma_buf, dev->dev);  	if (IS_ERR(attach)) -		return ERR_PTR(PTR_ERR(attach)); +		return ERR_CAST(attach);  	sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);  	if (IS_ERR(sg)) { diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index f5dd89e891d..9159d48d1df 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -354,8 +354,7 @@ static int udl_crtc_mode_set(struct drm_crtc *crtc,  static void udl_crtc_disable(struct drm_crtc *crtc)  { - - +	udl_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);  }  static void udl_crtc_destroy(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index e927b4c052f..af1b914b17e 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = {  	.mmap = drm_mmap,  	.poll = drm_poll,  	.fasync = drm_fasync, +#ifdef CONFIG_COMPAT +	.compat_ioctl = drm_compat_ioctl, +#endif  	.llseek = noop_llseek,  }; diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig index 794ff67c570..b71bcd0bfbb 100644 --- a/drivers/gpu/drm/vmwgfx/Kconfig +++ b/drivers/gpu/drm/vmwgfx/Kconfig @@ -12,3 +12,11 @@ config DRM_VMWGFX  	  This is a KMS enabled DRM driver for the VMware SVGA2  	  virtual hardware.  	  The compiled module will be called "vmwgfx.ko". + +config DRM_VMWGFX_FBCON +	depends on DRM_VMWGFX +	bool "Enable framebuffer console under vmwgfx by default" +	help +	   Choose this option if you are shipping a new vmwgfx +	   userspace driver that supports using the kernel driver. + diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4d9edead01a..ba2c35dbf10 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,8 +182,9 @@ static struct pci_device_id vmw_pci_id_list[] = {  	{0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},  	{0, 0, 0}  }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); -static int enable_fbdev; +static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);  static int vmw_probe(struct pci_dev *, const struct pci_device_id *);  static void vmw_master_init(struct vmw_master *); @@ -1154,6 +1155,11 @@ static struct drm_driver driver = {  	.open = vmw_driver_open,  	.preclose = vmw_preclose,  	.postclose = vmw_postclose, + +	.dumb_create = vmw_dumb_create, +	.dumb_map_offset = vmw_dumb_map_offset, +	.dumb_destroy = vmw_dumb_destroy, +  	.fops = &vmwgfx_driver_fops,  	.name = VMWGFX_DRIVER_NAME,  	.desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee2..29c984ff7f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv,  int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,  				struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, +		    struct drm_device *dev, +		    struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, +			struct drm_device *dev, uint32_t handle, +			uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, +		     struct drm_device *dev, +		     uint32_t handle);  /**   * Overlay control - vmwgfx_overlay.c   */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 6b0078ffa76..c50724bd30f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,15 +1688,19 @@ int vmw_du_page_flip(struct drm_crtc *crtc,  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);  	struct drm_framebuffer *old_fb = crtc->fb;  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); -	struct drm_file *file_priv = event->base.file_priv; +	struct drm_file *file_priv ;  	struct vmw_fence_obj *fence = NULL;  	struct drm_clip_rect clips;  	int ret; +	if (event == NULL) +		return -EINVAL; +  	/* require ScreenObject support for page flipping */  	if (!dev_priv->sou_priv)  		return -ENOSYS; +	file_priv = event->base.file_priv;  	if (!vmw_kms_screen_object_flippable(dev_priv, crtc))  		return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 22bf9a21ec7..2c6ffe0e2c0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ err_ref:  	vmw_resource_unreference(&res);  	return ret;  } + + +int vmw_dumb_create(struct drm_file *file_priv, +		    struct drm_device *dev, +		    struct drm_mode_create_dumb *args) +{ +	struct vmw_private *dev_priv = vmw_priv(dev); +	struct vmw_master *vmaster = vmw_master(file_priv->master); +	struct vmw_user_dma_buffer *vmw_user_bo; +	struct ttm_buffer_object *tmp; +	int ret; + +	args->pitch = args->width * ((args->bpp + 7) / 8); +	args->size = args->pitch * args->height; + +	vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); +	if (vmw_user_bo == NULL) +		return -ENOMEM; + +	ret = ttm_read_lock(&vmaster->lock, true); +	if (ret != 0) { +		kfree(vmw_user_bo); +		return ret; +	} + +	ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, +			      &vmw_vram_sys_placement, true, +			      &vmw_user_dmabuf_destroy); +	if (ret != 0) +		goto out_no_dmabuf; + +	tmp = ttm_bo_reference(&vmw_user_bo->dma.base); +	ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, +				   &vmw_user_bo->base, +				   false, +				   ttm_buffer_type, +				   &vmw_user_dmabuf_release, NULL); +	if (unlikely(ret != 0)) +		goto out_no_base_object; + +	args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: +	ttm_bo_unref(&tmp); +out_no_dmabuf: +	ttm_read_unlock(&vmaster->lock); +	return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, +			struct drm_device *dev, uint32_t handle, +			uint64_t *offset) +{ +	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; +	struct vmw_dma_buffer *out_buf; +	int ret; + +	ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); +	if (ret != 0) +		return -EINVAL; + +	*offset = out_buf->base.addr_space_offset; +	vmw_dmabuf_unreference(&out_buf); +	return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, +		     struct drm_device *dev, +		     uint32_t handle) +{ +	return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, +					 handle, TTM_REF_USAGE); +}  |