diff --git a/[refs] b/[refs] index 0dee32dd5aec..c3a9268986ac 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5438ae88d098c086cfb94be5327c49a04fc6bfd7 +refs/heads/master: 578393cd1e6ebe2979664f11df630126c3f348a8 diff --git a/trunk/drivers/gpu/drm/Kconfig b/trunk/drivers/gpu/drm/Kconfig index e405e61c27e2..b493663c7ba7 100644 --- a/trunk/drivers/gpu/drm/Kconfig +++ b/trunk/drivers/gpu/drm/Kconfig @@ -158,5 +158,3 @@ config DRM_SAVAGE help Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister chipset. If M is selected the module will be called savage. - -source "drivers/gpu/drm/exynos/Kconfig" \ No newline at end of file diff --git a/trunk/drivers/gpu/drm/Makefile b/trunk/drivers/gpu/drm/Makefile index c0496f660707..89cf05a72d1c 100644 --- a/trunk/drivers/gpu/drm/Makefile +++ b/trunk/drivers/gpu/drm/Makefile @@ -35,5 +35,4 @@ obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ -obj-$(CONFIG_DRM_EXYNOS) +=exynos/ obj-y += i2c/ diff --git a/trunk/drivers/gpu/drm/exynos/Kconfig b/trunk/drivers/gpu/drm/exynos/Kconfig deleted file mode 100644 index 847466aab435..000000000000 --- a/trunk/drivers/gpu/drm/exynos/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -config DRM_EXYNOS - tristate "DRM Support for Samsung SoC EXYNOS Series" - depends on DRM && PLAT_SAMSUNG - default n - select DRM_KMS_HELPER - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE - help - Choose this option if you have a Samsung SoC EXYNOS chipset. - If M is selected the module will be called exynosdrm. - -config DRM_EXYNOS_FIMD - tristate "Exynos DRM FIMD" - depends on DRM_EXYNOS - default n - help - Choose this option if you want to use Exynos FIMD for DRM. - If M is selected, the module will be called exynos_drm_fimd diff --git a/trunk/drivers/gpu/drm/exynos/Makefile b/trunk/drivers/gpu/drm/exynos/Makefile deleted file mode 100644 index 0496d3ff2683..000000000000 --- a/trunk/drivers/gpu/drm/exynos/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/exynos -exynosdrm-y := exynos_drm_drv.o exynos_drm_encoder.o exynos_drm_connector.o \ - exynos_drm_crtc.o exynos_drm_fbdev.o exynos_drm_fb.o \ - exynos_drm_buf.o exynos_drm_gem.o exynos_drm_core.o - -obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o -obj-$(CONFIG_DRM_EXYNOS_FIMD) += exynos_drm_fimd.o diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c deleted file mode 100644 index 6f8afea94fc9..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ /dev/null @@ -1,110 +0,0 @@ -/* exynos_drm_buf.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_buf.h" - -static DEFINE_MUTEX(exynos_drm_buf_lock); - -static int lowlevel_buffer_allocate(struct drm_device *dev, - struct exynos_drm_buf_entry *entry) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size, - (dma_addr_t *)&entry->paddr, GFP_KERNEL); - if (!entry->paddr) { - DRM_ERROR("failed to allocate buffer.\n"); - return -ENOMEM; - } - - DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n", - (unsigned int)entry->vaddr, entry->paddr, entry->size); - - return 0; -} - -static void lowlevel_buffer_deallocate(struct drm_device *dev, - struct exynos_drm_buf_entry *entry) -{ - DRM_DEBUG_KMS("%s.\n", __FILE__); - - if (entry->paddr && entry->vaddr && entry->size) - dma_free_writecombine(dev->dev, entry->size, entry->vaddr, - entry->paddr); - else - DRM_DEBUG_KMS("entry data is null.\n"); -} - -struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev, - unsigned int size) -{ - struct exynos_drm_buf_entry *entry; - - DRM_DEBUG_KMS("%s.\n", __FILE__); - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n"); - return ERR_PTR(-ENOMEM); - } - - entry->size = size; - - /* - * allocate memory region with size and set the memory information - * to vaddr and paddr of a entry object. - */ - if (lowlevel_buffer_allocate(dev, entry) < 0) { - kfree(entry); - entry = NULL; - return ERR_PTR(-ENOMEM); - } - - return entry; -} - -void exynos_drm_buf_destroy(struct drm_device *dev, - struct exynos_drm_buf_entry *entry) -{ - DRM_DEBUG_KMS("%s.\n", __FILE__); - - if (!entry) { - DRM_DEBUG_KMS("entry is null.\n"); - return; - } - - lowlevel_buffer_deallocate(dev, entry); - - kfree(entry); - entry = NULL; -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM Buffer Management Module"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h deleted file mode 100644 index 9b1f0fb8d3a5..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_buf.h +++ /dev/null @@ -1,50 +0,0 @@ -/* exynos_drm_buf.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_BUF_H_ -#define _EXYNOS_DRM_BUF_H_ - -/* - * exynos drm buffer entry structure. - * - * @paddr: physical address of allocated memory. - * @vaddr: kernel virtual address of allocated memory. - * @size: size of allocated memory. - */ -struct exynos_drm_buf_entry { - dma_addr_t paddr; - void __iomem *vaddr; - unsigned int size; -}; - -/* allocate physical memory. */ -struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev, - unsigned int size); - -/* remove allocated physical memory. */ -void exynos_drm_buf_destroy(struct drm_device *dev, - struct exynos_drm_buf_entry *entry); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.c deleted file mode 100644 index 985d9e768728..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" - -#define MAX_EDID 256 -#define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ - drm_connector) - -struct exynos_drm_connector { - struct drm_connector drm_connector; -}; - -/* convert exynos_video_timings to drm_display_mode */ -static inline void -convert_to_display_mode(struct drm_display_mode *mode, - struct fb_videomode *timing) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode->clock = timing->pixclock / 1000; - - mode->hdisplay = timing->xres; - mode->hsync_start = mode->hdisplay + timing->left_margin; - mode->hsync_end = mode->hsync_start + timing->hsync_len; - mode->htotal = mode->hsync_end + timing->right_margin; - - mode->vdisplay = timing->yres; - mode->vsync_start = mode->vdisplay + timing->upper_margin; - mode->vsync_end = mode->vsync_start + timing->vsync_len; - mode->vtotal = mode->vsync_end + timing->lower_margin; -} - -/* convert drm_display_mode to exynos_video_timings */ -static inline void -convert_to_video_timing(struct fb_videomode *timing, - struct drm_display_mode *mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - memset(timing, 0, sizeof(*timing)); - - timing->pixclock = mode->clock * 1000; - timing->refresh = mode->vrefresh; - - timing->xres = mode->hdisplay; - timing->left_margin = mode->hsync_start - mode->hdisplay; - timing->hsync_len = mode->hsync_end - mode->hsync_start; - timing->right_margin = mode->htotal - mode->hsync_end; - - timing->yres = mode->vdisplay; - timing->upper_margin = mode->vsync_start - mode->vdisplay; - timing->vsync_len = mode->vsync_end - mode->vsync_start; - timing->lower_margin = mode->vtotal - mode->vsync_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - timing->vmode = FB_VMODE_INTERLACED; - else - timing->vmode = FB_VMODE_NONINTERLACED; - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - timing->vmode |= FB_VMODE_DOUBLE; -} - -static int exynos_drm_connector_get_modes(struct drm_connector *connector) -{ - struct exynos_drm_manager *manager = - exynos_drm_get_manager(connector->encoder); - struct exynos_drm_display *display = manager->display; - unsigned int count; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!display) { - DRM_DEBUG_KMS("display is null.\n"); - return 0; - } - - /* - * if get_edid() exists then get_edid() callback of hdmi side - * is called to get edid data through i2c interface else - * get timing from the FIMD driver(display controller). - * - * P.S. in case of lcd panel, count is always 1 if success - * because lcd panel has only one mode. - */ - if (display->get_edid) { - int ret; - void *edid; - - edid = kzalloc(MAX_EDID, GFP_KERNEL); - if (!edid) { - DRM_ERROR("failed to allocate edid\n"); - return 0; - } - - ret = display->get_edid(manager->dev, connector, - edid, MAX_EDID); - if (ret < 0) { - DRM_ERROR("failed to get edid data.\n"); - kfree(edid); - edid = NULL; - return 0; - } - - drm_mode_connector_update_edid_property(connector, edid); - count = drm_add_edid_modes(connector, edid); - - kfree(connector->display_info.raw_edid); - connector->display_info.raw_edid = edid; - } else { - struct drm_display_mode *mode = drm_mode_create(connector->dev); - struct fb_videomode *timing; - - if (display->get_timing) - timing = display->get_timing(manager->dev); - else { - drm_mode_destroy(connector->dev, mode); - return 0; - } - - convert_to_display_mode(mode, timing); - - mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - count = 1; - } - - return count; -} - -static int exynos_drm_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct exynos_drm_manager *manager = - exynos_drm_get_manager(connector->encoder); - struct exynos_drm_display *display = manager->display; - struct fb_videomode timing; - int ret = MODE_BAD; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - convert_to_video_timing(&timing, mode); - - if (display && display->check_timing) - if (!display->check_timing(manager->dev, (void *)&timing)) - ret = MODE_OK; - - return ret; -} - -struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return connector->encoder; -} - -static struct drm_connector_helper_funcs exynos_connector_helper_funcs = { - .get_modes = exynos_drm_connector_get_modes, - .mode_valid = exynos_drm_connector_mode_valid, - .best_encoder = exynos_drm_best_encoder, -}; - -/* get detection status of display device. */ -static enum drm_connector_status -exynos_drm_connector_detect(struct drm_connector *connector, bool force) -{ - struct exynos_drm_manager *manager = - exynos_drm_get_manager(connector->encoder); - struct exynos_drm_display *display = manager->display; - enum drm_connector_status status = connector_status_disconnected; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (display && display->is_connected) { - if (display->is_connected(manager->dev)) - status = connector_status_connected; - else - status = connector_status_disconnected; - } - - return status; -} - -static void exynos_drm_connector_destroy(struct drm_connector *connector) -{ - struct exynos_drm_connector *exynos_connector = - to_exynos_connector(connector); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(exynos_connector); -} - -static struct drm_connector_funcs exynos_connector_funcs = { - .dpms = drm_helper_connector_dpms, - .fill_modes = drm_helper_probe_single_connector_modes, - .detect = exynos_drm_connector_detect, - .destroy = exynos_drm_connector_destroy, -}; - -struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, - struct drm_encoder *encoder) -{ - struct exynos_drm_connector *exynos_connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct drm_connector *connector; - int type; - int err; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL); - if (!exynos_connector) { - DRM_ERROR("failed to allocate connector\n"); - return NULL; - } - - connector = &exynos_connector->drm_connector; - - switch (manager->display->type) { - case EXYNOS_DISPLAY_TYPE_HDMI: - type = DRM_MODE_CONNECTOR_HDMIA; - break; - default: - type = DRM_MODE_CONNECTOR_Unknown; - break; - } - - drm_connector_init(dev, connector, &exynos_connector_funcs, type); - drm_connector_helper_add(connector, &exynos_connector_helper_funcs); - - err = drm_sysfs_connector_add(connector); - if (err) - goto err_connector; - - connector->encoder = encoder; - err = drm_mode_connector_attach_encoder(connector, encoder); - if (err) { - DRM_ERROR("failed to attach a connector to a encoder\n"); - goto err_sysfs; - } - - DRM_DEBUG_KMS("connector has been created\n"); - - return connector; - -err_sysfs: - drm_sysfs_connector_remove(connector); -err_connector: - drm_connector_cleanup(connector); - kfree(exynos_connector); - return NULL; -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM Connector Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.h deleted file mode 100644 index 1c7b2b5b579c..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_connector.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_CONNECTOR_H_ -#define _EXYNOS_DRM_CONNECTOR_H_ - -struct drm_connector *exynos_drm_connector_create(struct drm_device *dev, - struct drm_encoder *encoder); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_core.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_core.c deleted file mode 100644 index edb0ee13cffc..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_core.c +++ /dev/null @@ -1,272 +0,0 @@ -/* exynos_drm_core.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "exynos_drm_drv.h" -#include "exynos_drm_encoder.h" -#include "exynos_drm_connector.h" -#include "exynos_drm_fbdev.h" - -static DEFINE_MUTEX(exynos_drm_mutex); -static LIST_HEAD(exynos_drm_subdrv_list); -static struct drm_device *drm_dev; - -static int exynos_drm_subdrv_probe(struct drm_device *dev, - struct exynos_drm_subdrv *subdrv) -{ - struct drm_encoder *encoder; - struct drm_connector *connector; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (subdrv->probe) { - int ret; - - /* - * this probe callback would be called by sub driver - * after setting of all resources to this sub driver, - * such as clock, irq and register map are done or by load() - * of exynos drm driver. - * - * P.S. note that this driver is considered for modularization. - */ - ret = subdrv->probe(dev); - if (ret) - return ret; - } - - /* create and initialize a encoder for this sub driver. */ - encoder = exynos_drm_encoder_create(dev, &subdrv->manager, - (1 << MAX_CRTC) - 1); - if (!encoder) { - DRM_ERROR("failed to create encoder\n"); - return -EFAULT; - } - - /* - * create and initialize a connector for this sub driver and - * attach the encoder created above to the connector. - */ - connector = exynos_drm_connector_create(dev, encoder); - if (!connector) { - DRM_ERROR("failed to create connector\n"); - encoder->funcs->destroy(encoder); - return -EFAULT; - } - - subdrv->encoder = encoder; - subdrv->connector = connector; - - return 0; -} - -static void exynos_drm_subdrv_remove(struct drm_device *dev, - struct exynos_drm_subdrv *subdrv) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (subdrv->remove) - subdrv->remove(dev); - - if (subdrv->encoder) { - struct drm_encoder *encoder = subdrv->encoder; - encoder->funcs->destroy(encoder); - subdrv->encoder = NULL; - } - - if (subdrv->connector) { - struct drm_connector *connector = subdrv->connector; - connector->funcs->destroy(connector); - subdrv->connector = NULL; - } -} - -int exynos_drm_device_register(struct drm_device *dev) -{ - struct exynos_drm_subdrv *subdrv, *n; - int err; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!dev) - return -EINVAL; - - if (drm_dev) { - DRM_ERROR("Already drm device were registered\n"); - return -EBUSY; - } - - mutex_lock(&exynos_drm_mutex); - list_for_each_entry_safe(subdrv, n, &exynos_drm_subdrv_list, list) { - err = exynos_drm_subdrv_probe(dev, subdrv); - if (err) { - DRM_DEBUG("exynos drm subdrv probe failed.\n"); - list_del(&subdrv->list); - } - } - - drm_dev = dev; - mutex_unlock(&exynos_drm_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_device_register); - -int exynos_drm_device_unregister(struct drm_device *dev) -{ - struct exynos_drm_subdrv *subdrv; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!dev || dev != drm_dev) { - WARN(1, "Unexpected drm device unregister!\n"); - return -EINVAL; - } - - mutex_lock(&exynos_drm_mutex); - list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) - exynos_drm_subdrv_remove(dev, subdrv); - - drm_dev = NULL; - mutex_unlock(&exynos_drm_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); - -static int exynos_drm_mode_group_reinit(struct drm_device *dev) -{ - struct drm_mode_group *group = &dev->primary->mode_group; - uint32_t *id_list = group->id_list; - int ret; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - ret = drm_mode_group_init_legacy_group(dev, group); - if (ret < 0) - return ret; - - kfree(id_list); - return 0; -} - -int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) -{ - int err; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!subdrv) - return -EINVAL; - - mutex_lock(&exynos_drm_mutex); - if (drm_dev) { - err = exynos_drm_subdrv_probe(drm_dev, subdrv); - if (err) { - DRM_ERROR("failed to probe exynos drm subdrv\n"); - mutex_unlock(&exynos_drm_mutex); - return err; - } - - /* - * if any specific driver such as fimd or hdmi driver called - * exynos_drm_subdrv_register() later than drm_load(), - * the fb helper should be re-initialized and re-configured. - */ - err = exynos_drm_fbdev_reinit(drm_dev); - if (err) { - DRM_ERROR("failed to reinitialize exynos drm fbdev\n"); - exynos_drm_subdrv_remove(drm_dev, subdrv); - mutex_unlock(&exynos_drm_mutex); - return err; - } - - err = exynos_drm_mode_group_reinit(drm_dev); - if (err) { - DRM_ERROR("failed to reinitialize mode group\n"); - exynos_drm_fbdev_fini(drm_dev); - exynos_drm_subdrv_remove(drm_dev, subdrv); - mutex_unlock(&exynos_drm_mutex); - return err; - } - } - - subdrv->drm_dev = drm_dev; - - list_add_tail(&subdrv->list, &exynos_drm_subdrv_list); - mutex_unlock(&exynos_drm_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register); - -int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv) -{ - int ret = -EFAULT; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - if (!subdrv) { - DRM_DEBUG("Unexpected exynos drm subdrv unregister!\n"); - return ret; - } - - mutex_lock(&exynos_drm_mutex); - if (drm_dev) { - exynos_drm_subdrv_remove(drm_dev, subdrv); - list_del(&subdrv->list); - - /* - * fb helper should be updated once a sub driver is released - * to re-configure crtc and connector and also to re-setup - * drm framebuffer. - */ - ret = exynos_drm_fbdev_reinit(drm_dev); - if (ret < 0) { - DRM_ERROR("failed fb helper reinit.\n"); - goto fail; - } - - ret = exynos_drm_mode_group_reinit(drm_dev); - if (ret < 0) { - DRM_ERROR("failed drm mode group reinit.\n"); - goto fail; - } - } - -fail: - mutex_unlock(&exynos_drm_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(exynos_drm_subdrv_unregister); - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM Core Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c deleted file mode 100644 index 683ceb0f5277..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ /dev/null @@ -1,344 +0,0 @@ -/* exynos_drm_crtc.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_encoder.h" - -#define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ - drm_crtc) - -/* - * @fb_x: horizontal position from framebuffer base - * @fb_y: vertical position from framebuffer base - * @base_x: horizontal position from screen base - * @base_y: vertical position from screen base - * @crtc_w: width of crtc - * @crtc_h: height of crtc - */ -struct exynos_drm_crtc_pos { - unsigned int fb_x; - unsigned int fb_y; - unsigned int base_x; - unsigned int base_y; - unsigned int crtc_w; - unsigned int crtc_h; -}; - -/* - * Exynos specific crtc structure. - * - * @drm_crtc: crtc object. - * @overlay: contain information common to display controller and hdmi and - * contents of this overlay object would be copied to sub driver size. - * @pipe: a crtc index created at load() with a new crtc object creation - * and the crtc object would be set to private->crtc array - * to get a crtc object corresponding to this pipe from private->crtc - * array when irq interrupt occured. the reason of using this pipe is that - * drm framework doesn't support multiple irq yet. - * we can refer to the crtc to current hardware interrupt occured through - * this pipe value. - */ -struct exynos_drm_crtc { - struct drm_crtc drm_crtc; - struct exynos_drm_overlay overlay; - unsigned int pipe; -}; - -void exynos_drm_crtc_apply(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_overlay *overlay = &exynos_crtc->overlay; - - exynos_drm_fn_encoder(crtc, overlay, - exynos_drm_encoder_crtc_mode_set); - exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit); -} - -static void exynos_drm_overlay_update(struct exynos_drm_overlay *overlay, - struct drm_framebuffer *fb, - struct drm_display_mode *mode, - struct exynos_drm_crtc_pos *pos) -{ - struct exynos_drm_buffer_info buffer_info; - unsigned int actual_w = pos->crtc_w; - unsigned int actual_h = pos->crtc_h; - unsigned int hw_w; - unsigned int hw_h; - - /* update buffer address of framebuffer. */ - exynos_drm_fb_update_buf_off(fb, pos->fb_x, pos->fb_y, &buffer_info); - overlay->paddr = buffer_info.paddr; - overlay->vaddr = buffer_info.vaddr; - - hw_w = mode->hdisplay - pos->base_x; - hw_h = mode->vdisplay - pos->base_y; - - if (actual_w > hw_w) - actual_w = hw_w; - if (actual_h > hw_h) - actual_h = hw_h; - - overlay->offset_x = pos->base_x; - overlay->offset_y = pos->base_y; - overlay->width = actual_w; - overlay->height = actual_h; - overlay->bpp = fb->bits_per_pixel; - - DRM_DEBUG_KMS("overlay : offset_x/y(%d,%d), width/height(%d,%d)", - overlay->offset_x, overlay->offset_y, - overlay->width, overlay->height); - - overlay->buf_offsize = fb->width - actual_w; - overlay->line_size = actual_w; -} - -static int exynos_drm_crtc_update(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc; - struct exynos_drm_overlay *overlay; - struct exynos_drm_crtc_pos pos; - struct drm_display_mode *mode = &crtc->mode; - struct drm_framebuffer *fb = crtc->fb; - - if (!mode || !fb) - return -EINVAL; - - exynos_crtc = to_exynos_crtc(crtc); - overlay = &exynos_crtc->overlay; - - memset(&pos, 0, sizeof(struct exynos_drm_crtc_pos)); - pos.fb_x = crtc->x; - pos.fb_y = crtc->y; - pos.crtc_w = fb->width - crtc->x; - pos.crtc_h = fb->height - crtc->y; - - exynos_drm_overlay_update(overlay, crtc->fb, mode, &pos); - - return 0; -} - -static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO */ -} - -static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ -} - -static void exynos_drm_crtc_commit(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ -} - -static bool -exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL */ - return true; -} - -static int -exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y, - struct drm_framebuffer *old_fb) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode = adjusted_mode; - - return exynos_drm_crtc_update(crtc); -} - -static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - ret = exynos_drm_crtc_update(crtc); - if (ret) - return ret; - - exynos_drm_crtc_apply(crtc); - - return ret; -} - -static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - /* drm framework doesn't check NULL */ -} - -static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { - .dpms = exynos_drm_crtc_dpms, - .prepare = exynos_drm_crtc_prepare, - .commit = exynos_drm_crtc_commit, - .mode_fixup = exynos_drm_crtc_mode_fixup, - .mode_set = exynos_drm_crtc_mode_set, - .mode_set_base = exynos_drm_crtc_mode_set_base, - .load_lut = exynos_drm_crtc_load_lut, -}; - -static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) -{ - struct drm_device *dev = crtc->dev; - struct exynos_drm_private *dev_priv = dev->dev_private; - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct drm_framebuffer *old_fb = crtc->fb; - int ret = -EINVAL; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - if (event && !dev_priv->pageflip_event) { - list_add_tail(&event->base.link, - &dev_priv->pageflip_event_list); - - ret = drm_vblank_get(dev, exynos_crtc->pipe); - if (ret) { - DRM_DEBUG("failed to acquire vblank counter\n"); - goto out; - } - - crtc->fb = fb; - ret = exynos_drm_crtc_update(crtc); - if (ret) { - crtc->fb = old_fb; - drm_vblank_put(dev, exynos_crtc->pipe); - dev_priv->pageflip_event = false; - - goto out; - } - - dev_priv->pageflip_event = true; - } -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - struct exynos_drm_private *private = crtc->dev->dev_private; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - private->crtc[exynos_crtc->pipe] = NULL; - - drm_crtc_cleanup(crtc); - kfree(exynos_crtc); -} - -static struct drm_crtc_funcs exynos_crtc_funcs = { - .set_config = drm_crtc_helper_set_config, - .page_flip = exynos_drm_crtc_page_flip, - .destroy = exynos_drm_crtc_destroy, -}; - -struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev, - struct drm_crtc *crtc) -{ - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - - return &exynos_crtc->overlay; -} - -int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) -{ - struct exynos_drm_crtc *exynos_crtc; - struct exynos_drm_private *private = dev->dev_private; - struct drm_crtc *crtc; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); - if (!exynos_crtc) { - DRM_ERROR("failed to allocate exynos crtc\n"); - return -ENOMEM; - } - - exynos_crtc->pipe = nr; - crtc = &exynos_crtc->drm_crtc; - - private->crtc[nr] = crtc; - - drm_crtc_init(dev, crtc, &exynos_crtc_funcs); - drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); - - return 0; -} - -int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) -{ - struct exynos_drm_private *private = dev->dev_private; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, - exynos_drm_enable_vblank); - - return 0; -} - -void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) -{ - struct exynos_drm_private *private = dev->dev_private; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, - exynos_drm_disable_vblank); -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM CRTC Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.h deleted file mode 100644 index 452b62b23853..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_crtc.h +++ /dev/null @@ -1,39 +0,0 @@ -/* exynos_drm_crtc.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_CRTC_H_ -#define _EXYNOS_DRM_CRTC_H_ - -struct exynos_drm_overlay *get_exynos_drm_overlay(struct drm_device *dev, - struct drm_crtc *crtc); -void exynos_drm_crtc_apply(struct drm_crtc *crtc); -int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); -int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); -void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c deleted file mode 100644 index a190348ed9bd..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_crtc.h" -#include "exynos_drm_fbdev.h" -#include "exynos_drm_fb.h" -#include "exynos_drm_gem.h" - -#define DRIVER_NAME "exynos-drm" -#define DRIVER_DESC "Samsung SoC DRM" -#define DRIVER_DATE "20110530" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 0 - -static int exynos_drm_load(struct drm_device *dev, unsigned long flags) -{ - struct exynos_drm_private *private; - int ret; - int nr; - - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL); - if (!private) { - DRM_ERROR("failed to allocate private\n"); - return -ENOMEM; - } - - INIT_LIST_HEAD(&private->pageflip_event_list); - dev->dev_private = (void *)private; - - drm_mode_config_init(dev); - - exynos_drm_mode_config_init(dev); - - /* - * EXYNOS4 is enough to have two CRTCs and each crtc would be used - * without dependency of hardware. - */ - for (nr = 0; nr < MAX_CRTC; nr++) { - ret = exynos_drm_crtc_create(dev, nr); - if (ret) - goto err_crtc; - } - - ret = drm_vblank_init(dev, MAX_CRTC); - if (ret) - goto err_crtc; - - /* - * probe sub drivers such as display controller and hdmi driver, - * that were registered at probe() of platform driver - * to the sub driver and create encoder and connector for them. - */ - ret = exynos_drm_device_register(dev); - if (ret) - goto err_vblank; - - /* - * create and configure fb helper and also exynos specific - * fbdev object. - */ - ret = exynos_drm_fbdev_init(dev); - if (ret) { - DRM_ERROR("failed to initialize drm fbdev\n"); - goto err_drm_device; - } - - return 0; - -err_drm_device: - exynos_drm_device_unregister(dev); -err_vblank: - drm_vblank_cleanup(dev); -err_crtc: - drm_mode_config_cleanup(dev); - kfree(private); - - return ret; -} - -static int exynos_drm_unload(struct drm_device *dev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - exynos_drm_fbdev_fini(dev); - exynos_drm_device_unregister(dev); - drm_vblank_cleanup(dev); - drm_mode_config_cleanup(dev); - kfree(dev->dev_private); - - dev->dev_private = NULL; - - return 0; -} - -static void exynos_drm_lastclose(struct drm_device *dev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - exynos_drm_fbdev_restore_mode(dev); -} - -static struct vm_operations_struct exynos_drm_gem_vm_ops = { - .fault = exynos_drm_gem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static struct drm_ioctl_desc exynos_ioctls[] = { - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, - DRM_UNLOCKED | DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP_OFFSET, - exynos_drm_gem_map_offset_ioctl, DRM_UNLOCKED | - DRM_AUTH), - DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MMAP, - exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH), -}; - -static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_BUS_PLATFORM | - DRIVER_MODESET | DRIVER_GEM, - .load = exynos_drm_load, - .unload = exynos_drm_unload, - .lastclose = exynos_drm_lastclose, - .get_vblank_counter = drm_vblank_count, - .enable_vblank = exynos_drm_crtc_enable_vblank, - .disable_vblank = exynos_drm_crtc_disable_vblank, - .gem_init_object = exynos_drm_gem_init_object, - .gem_free_object = exynos_drm_gem_free_object, - .gem_vm_ops = &exynos_drm_gem_vm_ops, - .dumb_create = exynos_drm_gem_dumb_create, - .dumb_map_offset = exynos_drm_gem_dumb_map_offset, - .dumb_destroy = exynos_drm_gem_dumb_destroy, - .ioctls = exynos_ioctls, - .fops = { - .owner = THIS_MODULE, - .open = drm_open, - .mmap = exynos_drm_gem_mmap, - .poll = drm_poll, - .read = drm_read, - .unlocked_ioctl = drm_ioctl, - .release = drm_release, - }, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, -}; - -static int exynos_drm_platform_probe(struct platform_device *pdev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls); - - return drm_platform_init(&exynos_drm_driver, pdev); -} - -static int exynos_drm_platform_remove(struct platform_device *pdev) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - drm_platform_exit(&exynos_drm_driver, pdev); - - return 0; -} - -static struct platform_driver exynos_drm_platform_driver = { - .probe = exynos_drm_platform_probe, - .remove = __devexit_p(exynos_drm_platform_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - }, -}; - -static int __init exynos_drm_init(void) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - return platform_driver_register(&exynos_drm_platform_driver); -} - -static void __exit exynos_drm_exit(void) -{ - DRM_DEBUG_DRIVER("%s\n", __FILE__); - - platform_driver_unregister(&exynos_drm_platform_driver); -} - -module_init(exynos_drm_init); -module_exit(exynos_drm_exit); - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h deleted file mode 100644 index 832b6508adbd..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ /dev/null @@ -1,242 +0,0 @@ -/* exynos_drm_drv.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_DRV_H_ -#define _EXYNOS_DRM_DRV_H_ - -#include "drm.h" - -#define MAX_CRTC 2 - -struct drm_device; -struct exynos_drm_overlay; -struct drm_connector; - -/* this enumerates display type. */ -enum exynos_drm_output_type { - EXYNOS_DISPLAY_TYPE_NONE, - /* RGB or CPU Interface. */ - EXYNOS_DISPLAY_TYPE_LCD, - /* HDMI Interface. */ - EXYNOS_DISPLAY_TYPE_HDMI, -}; - -/* - * Exynos drm overlay ops structure. - * - * @mode_set: copy drm overlay info to hw specific overlay info. - * @commit: apply hardware specific overlay data to registers. - * @disable: disable hardware specific overlay. - */ -struct exynos_drm_overlay_ops { - void (*mode_set)(struct device *subdrv_dev, - struct exynos_drm_overlay *overlay); - void (*commit)(struct device *subdrv_dev); - void (*disable)(struct device *subdrv_dev); -}; - -/* - * Exynos drm common overlay structure. - * - * @offset_x: offset to x position. - * @offset_y: offset to y position. - * @width: window width. - * @height: window height. - * @bpp: pixel size.(in bit) - * @paddr: bus(accessed by dma) physical memory address to this overlay - * and this is physically continuous. - * @vaddr: virtual memory addresss to this overlay. - * @buf_off: start offset of framebuffer to be displayed. - * @buf_offsize: this value has result from - * (framebuffer width - display width) * bpp. - * @line_size: line size to this overlay memory in bytes. - * @default_win: a window to be enabled. - * @color_key: color key on or off. - * @index_color: if using color key feature then this value would be used - * as index color. - * @local_path: in case of lcd type, local path mode on or off. - * @transparency: transparency on or off. - * @activated: activated or not. - * - * this structure is common to exynos SoC and its contents would be copied - * to hardware specific overlay info. - */ -struct exynos_drm_overlay { - unsigned int offset_x; - unsigned int offset_y; - unsigned int width; - unsigned int height; - unsigned int bpp; - dma_addr_t paddr; - void __iomem *vaddr; - unsigned int buf_off; - unsigned int buf_offsize; - unsigned int line_size; - - bool default_win; - bool color_key; - unsigned int index_color; - bool local_path; - bool transparency; - bool activated; -}; - -/* - * Exynos DRM Display Structure. - * - this structure is common to analog tv, digital tv and lcd panel. - * - * @type: one of exynos_DISPLAY_TYPE_LCD and HDMI. - * @is_connected: check for that display is connected or not. - * @get_edid: get edid modes from display driver. - * @get_timing: get timing object from display driver. - * @check_timing: check if timing is valid or not. - * @power_on: display device on or off. - */ -struct exynos_drm_display { - enum exynos_drm_output_type type; - bool (*is_connected)(struct device *dev); - int (*get_edid)(struct device *dev, struct drm_connector *connector, - u8 *edid, int len); - void *(*get_timing)(struct device *dev); - int (*check_timing)(struct device *dev, void *timing); - int (*power_on)(struct device *dev, int mode); -}; - -/* - * Exynos drm manager ops - * - * @mode_set: convert drm_display_mode to hw specific display mode and - * would be called by encoder->mode_set(). - * @commit: set current hw specific display mode to hw. - * @enable_vblank: specific driver callback for enabling vblank interrupt. - * @disable_vblank: specific driver callback for disabling vblank interrupt. - */ -struct exynos_drm_manager_ops { - void (*mode_set)(struct device *subdrv_dev, void *mode); - void (*commit)(struct device *subdrv_dev); - int (*enable_vblank)(struct device *subdrv_dev); - void (*disable_vblank)(struct device *subdrv_dev); -}; - -/* - * Exynos drm common manager structure. - * - * @dev: pointer to device object for subdrv device driver. - * sub drivers such as display controller or hdmi driver, - * have their own device object. - * @ops: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control hardware global registers. - * @overlay_ops: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control hardware overlay reigsters. - * @display: pointer to callbacks for exynos drm specific framebuffer. - * these callbacks should be set by specific drivers such fimd - * or hdmi driver and are used to control display devices such as - * analog tv, digital tv and lcd panel and also get timing data for them. - */ -struct exynos_drm_manager { - struct device *dev; - int pipe; - struct exynos_drm_manager_ops *ops; - struct exynos_drm_overlay_ops *overlay_ops; - struct exynos_drm_display *display; -}; - -/* - * Exynos drm private structure. - */ -struct exynos_drm_private { - struct drm_fb_helper *fb_helper; - - /* for pageflip */ - struct list_head pageflip_event_list; - bool pageflip_event; - - /* - * created crtc object would be contained at this array and - * this array is used to be aware of which crtc did it request vblank. - */ - struct drm_crtc *crtc[MAX_CRTC]; -}; - -/* - * Exynos drm sub driver structure. - * - * @list: sub driver has its own list object to register to exynos drm driver. - * @drm_dev: pointer to drm_device and this pointer would be set - * when sub driver calls exynos_drm_subdrv_register(). - * @probe: this callback would be called by exynos drm driver after - * subdrv is registered to it. - * @remove: this callback is used to release resources created - * by probe callback. - * @manager: subdrv has its own manager to control a hardware appropriately - * and we can access a hardware drawing on this manager. - * @encoder: encoder object owned by this sub driver. - * @connector: connector object owned by this sub driver. - */ -struct exynos_drm_subdrv { - struct list_head list; - struct drm_device *drm_dev; - - int (*probe)(struct drm_device *dev); - void (*remove)(struct drm_device *dev); - - struct exynos_drm_manager manager; - struct drm_encoder *encoder; - struct drm_connector *connector; -}; - -/* - * this function calls a probe callback registered to sub driver list and - * create its own encoder and connector and then set drm_device object - * to global one. - */ -int exynos_drm_device_register(struct drm_device *dev); -/* - * this function calls a remove callback registered to sub driver list and - * destroy its own encoder and connetor. - */ -int exynos_drm_device_unregister(struct drm_device *dev); - -/* - * this function would be called by sub drivers such as display controller - * or hdmi driver to register this sub driver object to exynos drm driver - * and when a sub driver is registered to exynos drm driver a probe callback - * of the sub driver is called and creates its own encoder and connector - * and then fb helper and drm mode group would be re-initialized. - */ -int exynos_drm_subdrv_register(struct exynos_drm_subdrv *drm_subdrv); - -/* - * this function removes subdrv list from exynos drm driver and fb helper - * and drm mode group would be re-initialized. - */ -int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *drm_subdrv); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c deleted file mode 100644 index 7cf6fa86a67e..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ /dev/null @@ -1,271 +0,0 @@ -/* exynos_drm_encoder.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_crtc.h" -#include "exynos_drm_encoder.h" - -#define to_exynos_encoder(x) container_of(x, struct exynos_drm_encoder,\ - drm_encoder) - -/* - * exynos specific encoder structure. - * - * @drm_encoder: encoder object. - * @manager: specific encoder has its own manager to control a hardware - * appropriately and we can access a hardware drawing on this manager. - */ -struct exynos_drm_encoder { - struct drm_encoder drm_encoder; - struct exynos_drm_manager *manager; -}; - -static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - - DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode); - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - struct exynos_drm_display *display = manager->display; - - if (display && display->power_on) - display->power_on(manager->dev, mode); - } - } -} - -static bool -exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ - - return true; -} - -static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct drm_device *dev = encoder->dev; - struct drm_connector *connector; - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - struct exynos_drm_overlay *overlay = get_exynos_drm_overlay(dev, - encoder->crtc); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode = adjusted_mode; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder == encoder) { - if (manager_ops && manager_ops->mode_set) - manager_ops->mode_set(manager->dev, mode); - - if (overlay_ops && overlay_ops->mode_set) - overlay_ops->mode_set(manager->dev, overlay); - } - } -} - -static void exynos_drm_encoder_prepare(struct drm_encoder *encoder) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* drm framework doesn't check NULL. */ -} - -static void exynos_drm_encoder_commit(struct drm_encoder *encoder) -{ - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); - struct exynos_drm_manager_ops *manager_ops = manager->ops; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (manager_ops && manager_ops->commit) - manager_ops->commit(manager->dev); - - if (overlay_ops && overlay_ops->commit) - overlay_ops->commit(manager->dev); -} - -static struct drm_crtc * -exynos_drm_encoder_get_crtc(struct drm_encoder *encoder) -{ - return encoder->crtc; -} - -static struct drm_encoder_helper_funcs exynos_encoder_helper_funcs = { - .dpms = exynos_drm_encoder_dpms, - .mode_fixup = exynos_drm_encoder_mode_fixup, - .mode_set = exynos_drm_encoder_mode_set, - .prepare = exynos_drm_encoder_prepare, - .commit = exynos_drm_encoder_commit, - .get_crtc = exynos_drm_encoder_get_crtc, -}; - -static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) -{ - struct exynos_drm_encoder *exynos_encoder = - to_exynos_encoder(encoder); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_encoder->manager->pipe = -1; - - drm_encoder_cleanup(encoder); - encoder->dev->mode_config.num_encoder--; - kfree(exynos_encoder); -} - -static struct drm_encoder_funcs exynos_encoder_funcs = { - .destroy = exynos_drm_encoder_destroy, -}; - -struct drm_encoder * -exynos_drm_encoder_create(struct drm_device *dev, - struct exynos_drm_manager *manager, - unsigned int possible_crtcs) -{ - struct drm_encoder *encoder; - struct exynos_drm_encoder *exynos_encoder; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!manager || !possible_crtcs) - return NULL; - - if (!manager->dev) - return NULL; - - exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); - if (!exynos_encoder) { - DRM_ERROR("failed to allocate encoder\n"); - return NULL; - } - - exynos_encoder->manager = manager; - encoder = &exynos_encoder->drm_encoder; - encoder->possible_crtcs = possible_crtcs; - - DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); - - drm_encoder_init(dev, encoder, &exynos_encoder_funcs, - DRM_MODE_ENCODER_TMDS); - - drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); - - DRM_DEBUG_KMS("encoder has been created\n"); - - return encoder; -} - -struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) -{ - return to_exynos_encoder(encoder)->manager; -} - -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, - void (*fn)(struct drm_encoder *, void *)) -{ - struct drm_device *dev = crtc->dev; - struct drm_encoder *encoder; - - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc != crtc) - continue; - - fn(encoder, data); - } -} - -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - int crtc = *(int *)data; - - if (manager->pipe == -1) - manager->pipe = crtc; - - if (manager_ops->enable_vblank) - manager_ops->enable_vblank(manager->dev); -} - -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_manager_ops *manager_ops = manager->ops; - int crtc = *(int *)data; - - if (manager->pipe == -1) - manager->pipe = crtc; - - if (manager_ops->disable_vblank) - manager_ops->disable_vblank(manager->dev); -} - -void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - - overlay_ops->commit(manager->dev); -} - -void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data) -{ - struct exynos_drm_manager *manager = - to_exynos_encoder(encoder)->manager; - struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops; - struct exynos_drm_overlay *overlay = data; - - overlay_ops->mode_set(manager->dev, overlay); -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM Encoder Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h deleted file mode 100644 index 5ecd645d06a9..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_encoder.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_ENCODER_H_ -#define _EXYNOS_DRM_ENCODER_H_ - -struct exynos_drm_manager; - -struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, - struct exynos_drm_manager *mgr, - unsigned int possible_crtcs); -struct exynos_drm_manager * -exynos_drm_get_manager(struct drm_encoder *encoder); -void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, - void (*fn)(struct drm_encoder *, void *)); -void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); -void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data); -void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c deleted file mode 100644 index 4505d90d657a..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ /dev/null @@ -1,271 +0,0 @@ -/* exynos_drm_fb.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_fb.h" -#include "exynos_drm_buf.h" -#include "exynos_drm_gem.h" - -#define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) - -/* - * exynos specific framebuffer structure. - * - * @fb: drm framebuffer obejct. - * @exynos_gem_obj: exynos specific gem object containing a gem object. - * @entry: pointer to exynos drm buffer entry object. - * - containing only the information to physically continuous memory - * region allocated at default framebuffer creation. - */ -struct exynos_drm_fb { - struct drm_framebuffer fb; - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_buf_entry *entry; -}; - -static void exynos_drm_fb_destroy(struct drm_framebuffer *fb) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - drm_framebuffer_cleanup(fb); - - /* - * default framebuffer has no gem object so - * a buffer of the default framebuffer should be released at here. - */ - if (!exynos_fb->exynos_gem_obj && exynos_fb->entry) - exynos_drm_buf_destroy(fb->dev, exynos_fb->entry); - - kfree(exynos_fb); - exynos_fb = NULL; -} - -static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, - unsigned int *handle) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - return drm_gem_handle_create(file_priv, - &exynos_fb->exynos_gem_obj->base, handle); -} - -static int exynos_drm_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file_priv, unsigned flags, - unsigned color, struct drm_clip_rect *clips, - unsigned num_clips) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO */ - - return 0; -} - -static struct drm_framebuffer_funcs exynos_drm_fb_funcs = { - .destroy = exynos_drm_fb_destroy, - .create_handle = exynos_drm_fb_create_handle, - .dirty = exynos_drm_fb_dirty, -}; - -static struct drm_framebuffer * -exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev, - struct drm_mode_fb_cmd *mode_cmd) -{ - struct exynos_drm_fb *exynos_fb; - struct drm_framebuffer *fb; - struct exynos_drm_gem_obj *exynos_gem_obj = NULL; - struct drm_gem_object *obj; - unsigned int size; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mode_cmd->pitch = max(mode_cmd->pitch, - mode_cmd->width * (mode_cmd->bpp >> 3)); - - DRM_LOG_KMS("drm fb create(%dx%d)\n", - mode_cmd->width, mode_cmd->height); - - exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); - if (!exynos_fb) { - DRM_ERROR("failed to allocate exynos drm framebuffer.\n"); - return ERR_PTR(-ENOMEM); - } - - fb = &exynos_fb->fb; - ret = drm_framebuffer_init(dev, fb, &exynos_drm_fb_funcs); - if (ret) { - DRM_ERROR("failed to initialize framebuffer.\n"); - goto err_init; - } - - DRM_LOG_KMS("create: fb id: %d\n", fb->base.id); - - size = mode_cmd->pitch * mode_cmd->height; - - /* - * mode_cmd->handle could be NULL at booting time or - * with user request. if NULL, a new buffer or a gem object - * would be allocated. - */ - if (!mode_cmd->handle) { - if (!file_priv) { - struct exynos_drm_buf_entry *entry; - - /* - * in case that file_priv is NULL, it allocates - * only buffer and this buffer would be used - * for default framebuffer. - */ - entry = exynos_drm_buf_create(dev, size); - if (IS_ERR(entry)) { - ret = PTR_ERR(entry); - goto err_buffer; - } - - exynos_fb->entry = entry; - - DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n", - (unsigned long)entry->paddr, size); - - goto out; - } else { - exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, - size, - &mode_cmd->handle); - if (IS_ERR(exynos_gem_obj)) { - ret = PTR_ERR(exynos_gem_obj); - goto err_buffer; - } - } - } else { - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - goto err_buffer; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - drm_gem_object_unreference_unlocked(obj); - } - - /* - * if got a exynos_gem_obj from either a handle or - * a new creation then exynos_fb->exynos_gem_obj is NULL - * so that default framebuffer has no its own gem object, - * only its own buffer object. - */ - exynos_fb->entry = exynos_gem_obj->entry; - - DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n", - (unsigned long)exynos_fb->entry->paddr, size, - (unsigned int)&exynos_gem_obj->base); - -out: - exynos_fb->exynos_gem_obj = exynos_gem_obj; - - drm_helper_mode_fill_fb_struct(fb, mode_cmd); - - return fb; - -err_buffer: - drm_framebuffer_cleanup(fb); - -err_init: - kfree(exynos_fb); - - return ERR_PTR(ret); -} - -struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_mode_fb_cmd *mode_cmd) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return exynos_drm_fb_init(file_priv, dev, mode_cmd); -} - -void exynos_drm_fb_update_buf_off(struct drm_framebuffer *fb, - unsigned int x, unsigned int y, - struct exynos_drm_buffer_info *info) -{ - struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb); - struct exynos_drm_buf_entry *entry; - unsigned long offset; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - offset = x * (fb->bits_per_pixel >> 3); - offset += y * fb->pitch; - - entry = exynos_fb->entry; - - info->base_addr = entry->paddr; - info->vaddr = entry->vaddr + offset; - info->paddr = entry->paddr + offset; - - DRM_DEBUG_KMS("updated vaddr = 0x%lx, paddr = 0x%lx, offset = 0x%x\n", - (unsigned long)info->vaddr, (unsigned long)info->paddr, - (unsigned int)offset); -} - -static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = { - .fb_create = exynos_drm_fb_create, -}; - -void exynos_drm_mode_config_init(struct drm_device *dev) -{ - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - - /* - * set max width and height as default value(4096x4096). - * this value would be used to check framebuffer size limitation - * at drm_mode_addfb(). - */ - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - - dev->mode_config.funcs = &exynos_drm_mode_config_funcs; -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM FB Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h deleted file mode 100644 index eaa478abb6d1..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_FB_H_ -#define _EXYNOS_DRM_FB_H - -struct exynos_drm_buffer_info { - unsigned long base_addr; - dma_addr_t paddr; - void __iomem *vaddr; -}; - -void exynos_drm_fb_update_buf_off(struct drm_framebuffer *fb, - unsigned int x, unsigned int y, - struct exynos_drm_buffer_info *info); - -struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev, - struct drm_file *filp, - struct drm_mode_fb_cmd *mode_cmd); - -void exynos_drm_mode_config_init(struct drm_device *dev); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c deleted file mode 100644 index ac43bfc9e1f0..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ /dev/null @@ -1,441 +0,0 @@ -/* exynos_drm_fbdev.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm_crtc.h" -#include "drm_fb_helper.h" -#include "drm_crtc_helper.h" - -#include "exynos_drm_drv.h" -#include "exynos_drm_fb.h" - -#define MAX_CONNECTOR 4 -#define PREFERRED_BPP 32 - -#define to_exynos_fbdev(x) container_of(x, struct exynos_drm_fbdev,\ - drm_fb_helper) - -struct exynos_drm_fbdev { - struct drm_fb_helper drm_fb_helper; - struct drm_framebuffer *fb; -}; - -static int exynos_drm_fbdev_set_par(struct fb_info *info) -{ - struct fb_var_screeninfo *var = &info->var; - - switch (var->bits_per_pixel) { - case 32: - case 24: - case 18: - case 16: - case 12: - info->fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 1: - info->fix.visual = FB_VISUAL_MONO01; - break; - default: - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - break; - } - - info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; - - return drm_fb_helper_set_par(info); -} - - -static struct fb_ops exynos_drm_fb_ops = { - .owner = THIS_MODULE, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = exynos_drm_fbdev_set_par, - .fb_blank = drm_fb_helper_blank, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_setcmap = drm_fb_helper_setcmap, -}; - -static void exynos_drm_fbdev_update(struct drm_fb_helper *helper, - struct drm_framebuffer *fb, - unsigned int fb_width, - unsigned int fb_height) -{ - struct fb_info *fbi = helper->fbdev; - struct drm_device *dev = helper->dev; - struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper); - struct exynos_drm_buffer_info buffer_info; - unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_fb->fb = fb; - - drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth); - drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height); - - exynos_drm_fb_update_buf_off(fb, fbi->var.xoffset, fbi->var.yoffset, - &buffer_info); - - dev->mode_config.fb_base = buffer_info.base_addr; - - fbi->screen_base = buffer_info.vaddr; - fbi->screen_size = size; - fbi->fix.smem_start = buffer_info.paddr; - fbi->fix.smem_len = size; -} - -static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); - struct drm_device *dev = helper->dev; - struct fb_info *fbi; - struct drm_mode_fb_cmd mode_cmd = { 0 }; - struct platform_device *pdev = dev->platformdev; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n", - sizes->surface_width, sizes->surface_height, - sizes->surface_bpp); - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.bpp = sizes->surface_bpp; - mode_cmd.depth = sizes->surface_depth; - - mutex_lock(&dev->struct_mutex); - - fbi = framebuffer_alloc(0, &pdev->dev); - if (!fbi) { - DRM_ERROR("failed to allocate fb info.\n"); - ret = -ENOMEM; - goto out; - } - - exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd); - if (IS_ERR_OR_NULL(exynos_fbdev->fb)) { - DRM_ERROR("failed to create drm framebuffer.\n"); - ret = PTR_ERR(exynos_fbdev->fb); - goto out; - } - - helper->fb = exynos_fbdev->fb; - helper->fbdev = fbi; - - fbi->par = helper; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->fbops = &exynos_drm_fb_ops; - - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret) { - DRM_ERROR("failed to allocate cmap.\n"); - goto out; - } - - exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width, - sizes->fb_height); - -/* - * if failed, all resources allocated above would be released by - * drm_mode_config_cleanup() when drm_load() had been called prior - * to any specific driver such as fimd or hdmi driver. - */ -out: - mutex_unlock(&dev->struct_mutex); - return ret; -} - -static bool -exynos_drm_fbdev_is_samefb(struct drm_framebuffer *fb, - struct drm_fb_helper_surface_size *sizes) -{ - if (fb->width != sizes->surface_width) - return false; - if (fb->height != sizes->surface_height) - return false; - if (fb->bits_per_pixel != sizes->surface_bpp) - return false; - if (fb->depth != sizes->surface_depth) - return false; - - return true; -} - -static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct drm_device *dev = helper->dev; - struct exynos_drm_fbdev *exynos_fbdev = to_exynos_fbdev(helper); - struct drm_framebuffer *fb = exynos_fbdev->fb; - struct drm_mode_fb_cmd mode_cmd = { 0 }; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (helper->fb != fb) { - DRM_ERROR("drm framebuffer is different\n"); - return -EINVAL; - } - - if (exynos_drm_fbdev_is_samefb(fb, sizes)) - return 0; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.bpp = sizes->surface_bpp; - mode_cmd.depth = sizes->surface_depth; - - if (fb->funcs->destroy) - fb->funcs->destroy(fb); - - exynos_fbdev->fb = exynos_drm_fb_create(dev, NULL, &mode_cmd); - if (IS_ERR(exynos_fbdev->fb)) { - DRM_ERROR("failed to allocate fb.\n"); - return PTR_ERR(exynos_fbdev->fb); - } - - helper->fb = exynos_fbdev->fb; - exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width, - sizes->fb_height); - - return 0; -} - -static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - int ret = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!helper->fb) { - ret = exynos_drm_fbdev_create(helper, sizes); - if (ret < 0) { - DRM_ERROR("failed to create fbdev.\n"); - return ret; - } - - /* - * fb_helper expects a value more than 1 if succeed - * because register_framebuffer() should be called. - */ - ret = 1; - } else { - ret = exynos_drm_fbdev_recreate(helper, sizes); - if (ret < 0) { - DRM_ERROR("failed to reconfigure fbdev\n"); - return ret; - } - } - - return ret; -} - -static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = { - .fb_probe = exynos_drm_fbdev_probe, -}; - -int exynos_drm_fbdev_init(struct drm_device *dev) -{ - struct exynos_drm_fbdev *fbdev; - struct exynos_drm_private *private = dev->dev_private; - struct drm_fb_helper *helper; - unsigned int num_crtc; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) - return 0; - - fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); - if (!fbdev) { - DRM_ERROR("failed to allocate drm fbdev.\n"); - return -ENOMEM; - } - - private->fb_helper = helper = &fbdev->drm_fb_helper; - helper->funcs = &exynos_drm_fb_helper_funcs; - - num_crtc = dev->mode_config.num_crtc; - - ret = drm_fb_helper_init(dev, helper, num_crtc, MAX_CONNECTOR); - if (ret < 0) { - DRM_ERROR("failed to initialize drm fb helper.\n"); - goto err_init; - } - - ret = drm_fb_helper_single_add_all_connectors(helper); - if (ret < 0) { - DRM_ERROR("failed to register drm_fb_helper_connector.\n"); - goto err_setup; - - } - - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); - if (ret < 0) { - DRM_ERROR("failed to set up hw configuration.\n"); - goto err_setup; - } - - return 0; - -err_setup: - drm_fb_helper_fini(helper); - -err_init: - private->fb_helper = NULL; - kfree(fbdev); - - return ret; -} - -static void exynos_drm_fbdev_destroy(struct drm_device *dev, - struct drm_fb_helper *fb_helper) -{ - struct drm_framebuffer *fb; - - /* release drm framebuffer and real buffer */ - if (fb_helper->fb && fb_helper->fb->funcs) { - fb = fb_helper->fb; - if (fb && fb->funcs->destroy) - fb->funcs->destroy(fb); - } - - /* release linux framebuffer */ - if (fb_helper->fbdev) { - struct fb_info *info; - int ret; - - info = fb_helper->fbdev; - ret = unregister_framebuffer(info); - if (ret < 0) - DRM_DEBUG_KMS("failed unregister_framebuffer()\n"); - - if (info->cmap.len) - fb_dealloc_cmap(&info->cmap); - - framebuffer_release(info); - } - - drm_fb_helper_fini(fb_helper); -} - -void exynos_drm_fbdev_fini(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - struct exynos_drm_fbdev *fbdev; - - if (!private || !private->fb_helper) - return; - - fbdev = to_exynos_fbdev(private->fb_helper); - - exynos_drm_fbdev_destroy(dev, private->fb_helper); - kfree(fbdev); - private->fb_helper = NULL; -} - -void exynos_drm_fbdev_restore_mode(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - - if (!private || !private->fb_helper) - return; - - drm_fb_helper_restore_fbdev_mode(private->fb_helper); -} - -int exynos_drm_fbdev_reinit(struct drm_device *dev) -{ - struct exynos_drm_private *private = dev->dev_private; - struct drm_fb_helper *fb_helper; - int ret; - - if (!private) - return -EINVAL; - - if (!dev->mode_config.num_connector) { - exynos_drm_fbdev_fini(dev); - return 0; - } - - fb_helper = private->fb_helper; - - if (fb_helper) { - drm_fb_helper_fini(fb_helper); - - ret = drm_fb_helper_init(dev, fb_helper, - dev->mode_config.num_crtc, MAX_CONNECTOR); - if (ret < 0) { - DRM_ERROR("failed to initialize drm fb helper\n"); - return ret; - } - - ret = drm_fb_helper_single_add_all_connectors(fb_helper); - if (ret < 0) { - DRM_ERROR("failed to add fb helper to connectors\n"); - goto err; - } - - ret = drm_fb_helper_initial_config(fb_helper, PREFERRED_BPP); - if (ret < 0) { - DRM_ERROR("failed to set up hw configuration.\n"); - goto err; - } - } else { - /* - * if drm_load() failed whem drm load() was called prior - * to specific drivers, fb_helper must be NULL and so - * this fuction should be called again to re-initialize and - * re-configure the fb helper. it means that this function - * has been called by the specific drivers. - */ - return exynos_drm_fbdev_init(dev); - } - -err: - /* - * if drm_load() failed when drm load() was called prior - * to specific drivers, the fb_helper must be NULL and so check it. - */ - if (fb_helper) - drm_fb_helper_fini(fb_helper); - - return ret; -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Seung-Woo Kim "); -MODULE_DESCRIPTION("Samsung SoC DRM FBDEV Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.h deleted file mode 100644 index ccfce8a1a451..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_FBDEV_H_ -#define _EXYNOS_DRM_FBDEV_H_ - -int exynos_drm_fbdev_init(struct drm_device *dev); -int exynos_drm_fbdev_reinit(struct drm_device *dev); -void exynos_drm_fbdev_fini(struct drm_device *dev); -void exynos_drm_fbdev_restore_mode(struct drm_device *dev); - -#endif diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c deleted file mode 100644 index 620ad2d51368..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ /dev/null @@ -1,796 +0,0 @@ -/* exynos_drm_fimd.c - * - * Copyright (C) 2011 Samsung Electronics Co.Ltd - * Authors: - * Joonyoung Shim - * Inki Dae - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include "drmP.h" - -#include -#include -#include -#include - -#include -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_fbdev.h" -#include "exynos_drm_crtc.h" - -/* - * FIMD is stand for Fully Interactive Mobile Display and - * as a display controller, it transfers contents drawn on memory - * to a LCD Panel through Display Interfaces such as RGB or - * CPU Interface. - */ - -/* position control register for hardware window 0, 2 ~ 4.*/ -#define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) -#define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) -/* size control register for hardware window 0. */ -#define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08) -/* alpha control register for hardware window 1 ~ 4. */ -#define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16) -/* size control register for hardware window 1 ~ 4. */ -#define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) - -#define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) -#define VIDWx_BUF_END(win, buf) (VIDW_BUF_END(buf) + (win) * 8) -#define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) - -/* color key control register for hardware window 1 ~ 4. */ -#define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8)) -/* color key value register for hardware window 1 ~ 4. */ -#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8)) - -/* FIMD has totally five hardware windows. */ -#define WINDOWS_NR 5 - -#define get_fimd_context(dev) platform_get_drvdata(to_platform_device(dev)) - -struct fimd_win_data { - unsigned int offset_x; - unsigned int offset_y; - unsigned int width; - unsigned int height; - unsigned int bpp; - dma_addr_t paddr; - void __iomem *vaddr; - unsigned int buf_offsize; - unsigned int line_size; /* bytes */ -}; - -struct fimd_context { - struct exynos_drm_subdrv subdrv; - int irq; - struct drm_crtc *crtc; - struct clk *bus_clk; - struct clk *lcd_clk; - struct resource *regs_res; - void __iomem *regs; - struct fimd_win_data win_data[WINDOWS_NR]; - unsigned int clkdiv; - unsigned int default_win; - unsigned long irq_flags; - u32 vidcon0; - u32 vidcon1; - - struct fb_videomode *timing; -}; - -static bool fimd_display_is_connected(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ - - return true; -} - -static void *fimd_get_timing(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - return ctx->timing; -} - -static int fimd_check_timing(struct device *dev, void *timing) -{ - struct fimd_context *ctx = get_fimd_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ - - return 0; -} - -static int fimd_display_power_on(struct device *dev, int mode) -{ - struct fimd_context *ctx = get_fimd_context(dev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ - - return 0; -} - -static struct exynos_drm_display fimd_display = { - .type = EXYNOS_DISPLAY_TYPE_LCD, - .is_connected = fimd_display_is_connected, - .get_timing = fimd_get_timing, - .check_timing = fimd_check_timing, - .power_on = fimd_display_power_on, -}; - -static void fimd_commit(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - struct fb_videomode *timing = ctx->timing; - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* setup polarity values from machine code. */ - writel(ctx->vidcon1, ctx->regs + VIDCON1); - - /* setup vertical timing values. */ - val = VIDTCON0_VBPD(timing->upper_margin - 1) | - VIDTCON0_VFPD(timing->lower_margin - 1) | - VIDTCON0_VSPW(timing->vsync_len - 1); - writel(val, ctx->regs + VIDTCON0); - - /* setup horizontal timing values. */ - val = VIDTCON1_HBPD(timing->left_margin - 1) | - VIDTCON1_HFPD(timing->right_margin - 1) | - VIDTCON1_HSPW(timing->hsync_len - 1); - writel(val, ctx->regs + VIDTCON1); - - /* setup horizontal and vertical display size. */ - val = VIDTCON2_LINEVAL(timing->yres - 1) | - VIDTCON2_HOZVAL(timing->xres - 1); - writel(val, ctx->regs + VIDTCON2); - - /* setup clock source, clock divider, enable dma. */ - val = ctx->vidcon0; - val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); - - if (ctx->clkdiv > 1) - val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR; - else - val &= ~VIDCON0_CLKDIR; /* 1:1 clock */ - - /* - * fields of register with prefix '_F' would be updated - * at vsync(same as dma start) - */ - val |= VIDCON0_ENVID | VIDCON0_ENVID_F; - writel(val, ctx->regs + VIDCON0); -} - -static int fimd_enable_vblank(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!test_and_set_bit(0, &ctx->irq_flags)) { - val = readl(ctx->regs + VIDINTCON0); - - val |= VIDINTCON0_INT_ENABLE; - val |= VIDINTCON0_INT_FRAME; - - val &= ~VIDINTCON0_FRAMESEL0_MASK; - val |= VIDINTCON0_FRAMESEL0_VSYNC; - val &= ~VIDINTCON0_FRAMESEL1_MASK; - val |= VIDINTCON0_FRAMESEL1_NONE; - - writel(val, ctx->regs + VIDINTCON0); - } - - return 0; -} - -static void fimd_disable_vblank(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (test_and_clear_bit(0, &ctx->irq_flags)) { - val = readl(ctx->regs + VIDINTCON0); - - val &= ~VIDINTCON0_INT_FRAME; - val &= ~VIDINTCON0_INT_ENABLE; - - writel(val, ctx->regs + VIDINTCON0); - } -} - -static struct exynos_drm_manager_ops fimd_manager_ops = { - .commit = fimd_commit, - .enable_vblank = fimd_enable_vblank, - .disable_vblank = fimd_disable_vblank, -}; - -static void fimd_win_mode_set(struct device *dev, - struct exynos_drm_overlay *overlay) -{ - struct fimd_context *ctx = get_fimd_context(dev); - struct fimd_win_data *win_data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!overlay) { - dev_err(dev, "overlay is NULL\n"); - return; - } - - win_data = &ctx->win_data[ctx->default_win]; - - win_data->offset_x = overlay->offset_x; - win_data->offset_y = overlay->offset_y; - win_data->width = overlay->width; - win_data->height = overlay->height; - win_data->paddr = overlay->paddr; - win_data->vaddr = overlay->vaddr; - win_data->bpp = overlay->bpp; - win_data->buf_offsize = overlay->buf_offsize * (overlay->bpp >> 3); - win_data->line_size = overlay->line_size * (overlay->bpp >> 3); -} - -static void fimd_win_set_pixfmt(struct device *dev, unsigned int win) -{ - struct fimd_context *ctx = get_fimd_context(dev); - struct fimd_win_data *win_data = &ctx->win_data[win]; - unsigned long val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - val = WINCONx_ENWIN; - - switch (win_data->bpp) { - case 1: - val |= WINCON0_BPPMODE_1BPP; - val |= WINCONx_BITSWP; - val |= WINCONx_BURSTLEN_4WORD; - break; - case 2: - val |= WINCON0_BPPMODE_2BPP; - val |= WINCONx_BITSWP; - val |= WINCONx_BURSTLEN_8WORD; - break; - case 4: - val |= WINCON0_BPPMODE_4BPP; - val |= WINCONx_BITSWP; - val |= WINCONx_BURSTLEN_8WORD; - break; - case 8: - val |= WINCON0_BPPMODE_8BPP_PALETTE; - val |= WINCONx_BURSTLEN_8WORD; - val |= WINCONx_BYTSWP; - break; - case 16: - val |= WINCON0_BPPMODE_16BPP_565; - val |= WINCONx_HAWSWP; - val |= WINCONx_BURSTLEN_16WORD; - break; - case 24: - val |= WINCON0_BPPMODE_24BPP_888; - val |= WINCONx_WSWP; - val |= WINCONx_BURSTLEN_16WORD; - break; - case 32: - val |= WINCON1_BPPMODE_28BPP_A4888 - | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; - val |= WINCONx_WSWP; - val |= WINCONx_BURSTLEN_16WORD; - break; - default: - DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n"); - - val |= WINCON0_BPPMODE_24BPP_888; - val |= WINCONx_WSWP; - val |= WINCONx_BURSTLEN_16WORD; - break; - } - - DRM_DEBUG_KMS("bpp = %d\n", win_data->bpp); - - writel(val, ctx->regs + WINCON(win)); -} - -static void fimd_win_set_colkey(struct device *dev, unsigned int win) -{ - struct fimd_context *ctx = get_fimd_context(dev); - unsigned int keycon0 = 0, keycon1 = 0; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F | - WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0); - - keycon1 = WxKEYCON1_COLVAL(0xffffffff); - - writel(keycon0, ctx->regs + WKEYCON0_BASE(win)); - writel(keycon1, ctx->regs + WKEYCON1_BASE(win)); -} - -static void fimd_win_commit(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - struct fimd_win_data *win_data; - int win = ctx->default_win; - unsigned long val, alpha, size; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (win < 0 || win > WINDOWS_NR) - return; - - win_data = &ctx->win_data[win]; - - /* - * SHADOWCON register is used for enabling timing. - * - * for example, once only width value of a register is set, - * if the dma is started then fimd hardware could malfunction so - * with protect window setting, the register fields with prefix '_F' - * wouldn't be updated at vsync also but updated once unprotect window - * is set. - */ - - /* protect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); - - /* buffer start address */ - val = win_data->paddr; - writel(val, ctx->regs + VIDWx_BUF_START(win, 0)); - - /* buffer end address */ - size = win_data->width * win_data->height * (win_data->bpp >> 3); - val = win_data->paddr + size; - writel(val, ctx->regs + VIDWx_BUF_END(win, 0)); - - DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n", - (unsigned long)win_data->paddr, val, size); - - /* buffer size */ - val = VIDW_BUF_SIZE_OFFSET(win_data->buf_offsize) | - VIDW_BUF_SIZE_PAGEWIDTH(win_data->line_size); - writel(val, ctx->regs + VIDWx_BUF_SIZE(win, 0)); - - /* OSD position */ - val = VIDOSDxA_TOPLEFT_X(win_data->offset_x) | - VIDOSDxA_TOPLEFT_Y(win_data->offset_y); - writel(val, ctx->regs + VIDOSD_A(win)); - - val = VIDOSDxB_BOTRIGHT_X(win_data->offset_x + win_data->width - 1) | - VIDOSDxB_BOTRIGHT_Y(win_data->offset_y + win_data->height - 1); - writel(val, ctx->regs + VIDOSD_B(win)); - - DRM_DEBUG_KMS("osd pos: tx = %d, ty = %d, bx = %d, by = %x\n", - win_data->offset_x, win_data->offset_y, - win_data->offset_x + win_data->width - 1, - win_data->offset_y + win_data->height - 1); - - /* hardware window 0 doesn't support alpha channel. */ - if (win != 0) { - /* OSD alpha */ - alpha = VIDISD14C_ALPHA1_R(0xf) | - VIDISD14C_ALPHA1_G(0xf) | - VIDISD14C_ALPHA1_B(0xf); - - writel(alpha, ctx->regs + VIDOSD_C(win)); - } - - /* OSD size */ - if (win != 3 && win != 4) { - u32 offset = VIDOSD_D(win); - if (win == 0) - offset = VIDOSD_C_SIZE_W0; - val = win_data->width * win_data->height; - writel(val, ctx->regs + offset); - - DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); - } - - fimd_win_set_pixfmt(dev, win); - - /* hardware window 0 doesn't support color key. */ - if (win != 0) - fimd_win_set_colkey(dev, win); - - /* Enable DMA channel and unprotect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_CHx_ENABLE(win); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); -} - -static void fimd_win_disable(struct device *dev) -{ - struct fimd_context *ctx = get_fimd_context(dev); - struct fimd_win_data *win_data; - int win = ctx->default_win; - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (win < 0 || win > WINDOWS_NR) - return; - - win_data = &ctx->win_data[win]; - - /* protect windows */ - val = readl(ctx->regs + SHADOWCON); - val |= SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); - - /* wincon */ - val = readl(ctx->regs + WINCON(win)); - val &= ~WINCONx_ENWIN; - writel(val, ctx->regs + WINCON(win)); - - /* unprotect windows */ - val = readl(ctx->regs + SHADOWCON); - val &= ~SHADOWCON_CHx_ENABLE(win); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); -} - -static struct exynos_drm_overlay_ops fimd_overlay_ops = { - .mode_set = fimd_win_mode_set, - .commit = fimd_win_commit, - .disable = fimd_win_disable, -}; - -/* for pageflip event */ -static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc) -{ - struct exynos_drm_private *dev_priv = drm_dev->dev_private; - struct drm_pending_vblank_event *e, *t; - struct timeval now; - unsigned long flags; - - if (!dev_priv->pageflip_event) - return; - - spin_lock_irqsave(&drm_dev->event_lock, flags); - - exynos_drm_crtc_apply(dev_priv->crtc[crtc]); - - list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, - base.link) { - do_gettimeofday(&now); - e->event.sequence = 0; - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; - - list_move_tail(&e->base.link, &e->base.file_priv->event_list); - wake_up_interruptible(&e->base.file_priv->event_wait); - } - - drm_vblank_put(drm_dev, crtc); - dev_priv->pageflip_event = false; - - spin_unlock_irqrestore(&drm_dev->event_lock, flags); -} - -static irqreturn_t fimd_irq_handler(int irq, void *dev_id) -{ - struct fimd_context *ctx = (struct fimd_context *)dev_id; - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; - struct drm_device *drm_dev = subdrv->drm_dev; - struct device *dev = subdrv->manager.dev; - struct exynos_drm_manager *manager = &subdrv->manager; - u32 val; - - val = readl(ctx->regs + VIDINTCON1); - - if (val & VIDINTCON1_INT_FRAME) - /* VSYNC interrupt */ - writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); - - drm_handle_vblank(drm_dev, manager->pipe); - fimd_finish_pageflip(drm_dev, manager->pipe); - - return IRQ_HANDLED; -} - -static int fimd_subdrv_probe(struct drm_device *drm_dev) -{ - struct drm_driver *drm_driver = drm_dev->driver; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * enable drm irq mode. - * - with irq_enabled = 1, we can use the vblank feature. - * - * P.S. note that we wouldn't use drm irq handler but - * just specific driver own one instead because - * drm framework supports only one irq handler. - */ - drm_dev->irq_enabled = 1; - - /* - * with vblank_disable_allowed = 1, vblank interrupt will be disabled - * by drm timer once a current process gives up ownership of - * vblank event.(drm_vblank_put function was called) - */ - drm_dev->vblank_disable_allowed = 1; - - return 0; -} - -static void fimd_subdrv_remove(struct drm_device *drm_dev) -{ - struct drm_driver *drm_driver = drm_dev->driver; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* TODO. */ -} - -static int fimd_calc_clkdiv(struct fimd_context *ctx, - struct fb_videomode *timing) -{ - unsigned long clk = clk_get_rate(ctx->lcd_clk); - u32 retrace; - u32 clkdiv; - u32 best_framerate = 0; - u32 framerate; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - retrace = timing->left_margin + timing->hsync_len + - timing->right_margin + timing->xres; - retrace *= timing->upper_margin + timing->vsync_len + - timing->lower_margin + timing->yres; - - /* default framerate is 60Hz */ - if (!timing->refresh) - timing->refresh = 60; - - clk /= retrace; - - for (clkdiv = 1; clkdiv < 0x100; clkdiv++) { - int tmp; - - /* get best framerate */ - framerate = clk / clkdiv; - tmp = timing->refresh - framerate; - if (tmp < 0) { - best_framerate = framerate; - continue; - } else { - if (!best_framerate) - best_framerate = framerate; - else if (tmp < (best_framerate - framerate)) - best_framerate = framerate; - break; - } - } - - return clkdiv; -} - -static void fimd_clear_win(struct fimd_context *ctx, int win) -{ - u32 val; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - writel(0, ctx->regs + WINCON(win)); - writel(0, ctx->regs + VIDOSD_A(win)); - writel(0, ctx->regs + VIDOSD_B(win)); - writel(0, ctx->regs + VIDOSD_C(win)); - - if (win == 1 || win == 2) - writel(0, ctx->regs + VIDOSD_D(win)); - - val = readl(ctx->regs + SHADOWCON); - val &= ~SHADOWCON_WINx_PROTECT(win); - writel(val, ctx->regs + SHADOWCON); -} - -static int __devinit fimd_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct fimd_context *ctx; - struct exynos_drm_subdrv *subdrv; - struct exynos_drm_fimd_pdata *pdata; - struct fb_videomode *timing; - struct resource *res; - int win; - int ret = -EINVAL; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(dev, "no platform data specified\n"); - return -EINVAL; - } - - timing = &pdata->timing; - if (!timing) { - dev_err(dev, "timing is null.\n"); - return -EINVAL; - } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ctx->bus_clk = clk_get(dev, "fimd"); - if (IS_ERR(ctx->bus_clk)) { - dev_err(dev, "failed to get bus clock\n"); - ret = PTR_ERR(ctx->bus_clk); - goto err_clk_get; - } - - clk_enable(ctx->bus_clk); - - ctx->lcd_clk = clk_get(dev, "sclk_fimd"); - if (IS_ERR(ctx->lcd_clk)) { - dev_err(dev, "failed to get lcd clock\n"); - ret = PTR_ERR(ctx->lcd_clk); - goto err_bus_clk; - } - - clk_enable(ctx->lcd_clk); - - 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_res = request_mem_region(res->start, resource_size(res), - dev_name(dev)); - if (!ctx->regs_res) { - dev_err(dev, "failed to claim register region\n"); - ret = -ENOENT; - goto err_clk; - } - - ctx->regs = ioremap(res->start, resource_size(res)); - if (!ctx->regs) { - dev_err(dev, "failed to map registers\n"); - ret = -ENXIO; - goto err_req_region_io; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, "irq request failed.\n"); - goto err_req_region_irq; - } - - ctx->irq = res->start; - - for (win = 0; win < WINDOWS_NR; win++) - fimd_clear_win(ctx, win); - - ret = request_irq(ctx->irq, fimd_irq_handler, 0, "drm_fimd", ctx); - if (ret < 0) { - dev_err(dev, "irq request failed.\n"); - goto err_req_irq; - } - - ctx->clkdiv = fimd_calc_clkdiv(ctx, timing); - ctx->vidcon0 = pdata->vidcon0; - ctx->vidcon1 = pdata->vidcon1; - ctx->default_win = pdata->default_win; - ctx->timing = timing; - - timing->pixclock = clk_get_rate(ctx->lcd_clk) / ctx->clkdiv; - - DRM_DEBUG_KMS("pixel clock = %d, clkdiv = %d\n", - timing->pixclock, ctx->clkdiv); - - subdrv = &ctx->subdrv; - - subdrv->probe = fimd_subdrv_probe; - subdrv->remove = fimd_subdrv_remove; - subdrv->manager.pipe = -1; - subdrv->manager.ops = &fimd_manager_ops; - subdrv->manager.overlay_ops = &fimd_overlay_ops; - subdrv->manager.display = &fimd_display; - subdrv->manager.dev = dev; - - platform_set_drvdata(pdev, ctx); - exynos_drm_subdrv_register(subdrv); - - return 0; - -err_req_irq: -err_req_region_irq: - iounmap(ctx->regs); - -err_req_region_io: - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - -err_clk: - clk_disable(ctx->lcd_clk); - clk_put(ctx->lcd_clk); - -err_bus_clk: - clk_disable(ctx->bus_clk); - clk_put(ctx->bus_clk); - -err_clk_get: - kfree(ctx); - return ret; -} - -static int __devexit fimd_remove(struct platform_device *pdev) -{ - struct fimd_context *ctx = platform_get_drvdata(pdev); - - DRM_DEBUG_KMS("%s\n", __FILE__); - - exynos_drm_subdrv_unregister(&ctx->subdrv); - - clk_disable(ctx->lcd_clk); - clk_disable(ctx->bus_clk); - clk_put(ctx->lcd_clk); - clk_put(ctx->bus_clk); - - iounmap(ctx->regs); - release_resource(ctx->regs_res); - kfree(ctx->regs_res); - free_irq(ctx->irq, ctx); - - kfree(ctx); - - return 0; -} - -static struct platform_driver fimd_driver = { - .probe = fimd_probe, - .remove = __devexit_p(fimd_remove), - .driver = { - .name = "exynos4-fb", - .owner = THIS_MODULE, - }, -}; - -static int __init fimd_init(void) -{ - return platform_driver_register(&fimd_driver); -} - -static void __exit fimd_exit(void) -{ - platform_driver_unregister(&fimd_driver); -} - -module_init(fimd_init); -module_exit(fimd_exit); - -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung DRM FIMD Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c deleted file mode 100644 index a8e7a88906ed..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ /dev/null @@ -1,415 +0,0 @@ -/* exynos_drm_gem.c - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Author: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "drmP.h" -#include "drm.h" - -#include - -#include "exynos_drm_drv.h" -#include "exynos_drm_gem.h" -#include "exynos_drm_buf.h" - -static unsigned int convert_to_vm_err_msg(int msg) -{ - unsigned int out_msg; - - switch (msg) { - case 0: - case -ERESTARTSYS: - case -EINTR: - out_msg = VM_FAULT_NOPAGE; - break; - - case -ENOMEM: - out_msg = VM_FAULT_OOM; - break; - - default: - out_msg = VM_FAULT_SIGBUS; - break; - } - - return out_msg; -} - -static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; -} - -struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv, - struct drm_device *dev, unsigned int size, - unsigned int *handle) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct exynos_drm_buf_entry *entry; - struct drm_gem_object *obj; - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - size = roundup(size, PAGE_SIZE); - - exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL); - if (!exynos_gem_obj) { - DRM_ERROR("failed to allocate exynos gem object.\n"); - return ERR_PTR(-ENOMEM); - } - - /* allocate the new buffer object and memory region. */ - entry = exynos_drm_buf_create(dev, size); - if (!entry) { - kfree(exynos_gem_obj); - return ERR_PTR(-ENOMEM); - } - - exynos_gem_obj->entry = entry; - - obj = &exynos_gem_obj->base; - - ret = drm_gem_object_init(dev, obj, size); - if (ret < 0) { - DRM_ERROR("failed to initailize gem object.\n"); - goto err_obj_init; - } - - DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp); - - ret = drm_gem_create_mmap_offset(obj); - if (ret < 0) { - DRM_ERROR("failed to allocate mmap offset.\n"); - goto err_create_mmap_offset; - } - - /* - * allocate a id of idr table where the obj is registered - * and handle has the id what user can see. - */ - ret = drm_gem_handle_create(file_priv, obj, handle); - if (ret) - goto err_handle_create; - - DRM_DEBUG_KMS("gem handle = 0x%x\n", *handle); - - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_unreference_unlocked(obj); - - return exynos_gem_obj; - -err_handle_create: - drm_gem_free_mmap_offset(obj); - -err_create_mmap_offset: - drm_gem_object_release(obj); - -err_obj_init: - exynos_drm_buf_destroy(dev, exynos_gem_obj->entry); - - kfree(exynos_gem_obj); - - return ERR_PTR(ret); -} - -int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_create *args = data; - struct exynos_drm_gem_obj *exynos_gem_obj; - - DRM_DEBUG_KMS("%s : size = 0x%x\n", __FILE__, args->size); - - exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size, - &args->handle); - if (IS_ERR(exynos_gem_obj)) - return PTR_ERR(exynos_gem_obj); - - return 0; -} - -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_map_off *args = data; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n", - args->handle, (unsigned long)args->offset); - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - return exynos_drm_gem_dumb_map_offset(file_priv, dev, args->handle, - &args->offset); -} - -static int exynos_drm_gem_mmap_buffer(struct file *filp, - struct vm_area_struct *vma) -{ - struct drm_gem_object *obj = filp->private_data; - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct exynos_drm_buf_entry *entry; - unsigned long pfn, vm_size; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - vma->vm_flags |= (VM_IO | VM_RESERVED); - - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_file = filp; - - vm_size = vma->vm_end - vma->vm_start; - /* - * a entry contains information to physically continuous memory - * allocated by user request or at framebuffer creation. - */ - entry = exynos_gem_obj->entry; - - /* check if user-requested size is valid. */ - if (vm_size > entry->size) - return -EINVAL; - - /* - * get page frame number to physical memory to be mapped - * to user space. - */ - pfn = exynos_gem_obj->entry->paddr >> PAGE_SHIFT; - - DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn); - - if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, - vma->vm_page_prot)) { - DRM_ERROR("failed to remap pfn range.\n"); - return -EAGAIN; - } - - return 0; -} - -static const struct file_operations exynos_drm_gem_fops = { - .mmap = exynos_drm_gem_mmap_buffer, -}; - -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_exynos_gem_mmap *args = data; - struct drm_gem_object *obj; - unsigned int addr; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - if (!(dev->driver->driver_features & DRIVER_GEM)) { - DRM_ERROR("does not support GEM.\n"); - return -ENODEV; - } - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - return -EINVAL; - } - - obj->filp->f_op = &exynos_drm_gem_fops; - obj->filp->private_data = obj; - - down_write(¤t->mm->mmap_sem); - addr = do_mmap(obj->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, 0); - up_write(¤t->mm->mmap_sem); - - drm_gem_object_unreference_unlocked(obj); - - if (IS_ERR((void *)addr)) - return PTR_ERR((void *)addr); - - args->mapped = addr; - - DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); - - return 0; -} - -int exynos_drm_gem_init_object(struct drm_gem_object *obj) -{ - DRM_DEBUG_KMS("%s\n", __FILE__); - - return 0; -} - -void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - DRM_DEBUG_KMS("handle count = %d\n", - atomic_read(&gem_obj->handle_count)); - - if (gem_obj->map_list.map) - drm_gem_free_mmap_offset(gem_obj); - - /* release file pointer to gem object. */ - drm_gem_object_release(gem_obj); - - exynos_gem_obj = to_exynos_gem_obj(gem_obj); - - exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->entry); - - kfree(exynos_gem_obj); -} - -int exynos_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, struct drm_mode_create_dumb *args) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * alocate memory to be used for framebuffer. - * - this callback would be called by user application - * with DRM_IOCTL_MODE_CREATE_DUMB command. - */ - - args->pitch = args->width * args->bpp >> 3; - args->size = args->pitch * args->height; - - exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size, - &args->handle); - if (IS_ERR(exynos_gem_obj)) - return PTR_ERR(exynos_gem_obj); - - return 0; -} - -int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, uint64_t *offset) -{ - struct exynos_drm_gem_obj *exynos_gem_obj; - struct drm_gem_object *obj; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - mutex_lock(&dev->struct_mutex); - - /* - * get offset of memory allocated for drm framebuffer. - * - this callback would be called by user application - * with DRM_IOCTL_MODE_MAP_DUMB command. - */ - - obj = drm_gem_object_lookup(dev, file_priv, handle); - if (!obj) { - DRM_ERROR("failed to lookup gem object.\n"); - mutex_unlock(&dev->struct_mutex); - return -EINVAL; - } - - exynos_gem_obj = to_exynos_gem_obj(obj); - - *offset = get_gem_mmap_offset(&exynos_gem_obj->base); - - drm_gem_object_unreference(obj); - - DRM_DEBUG_KMS("offset = 0x%lx\n", (unsigned long)*offset); - - mutex_unlock(&dev->struct_mutex); - - return 0; -} - -int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct drm_gem_object *obj = vma->vm_private_data; - struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); - struct drm_device *dev = obj->dev; - unsigned long pfn; - pgoff_t page_offset; - int ret; - - page_offset = ((unsigned long)vmf->virtual_address - - vma->vm_start) >> PAGE_SHIFT; - - mutex_lock(&dev->struct_mutex); - - pfn = (exynos_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset; - - ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); - - mutex_unlock(&dev->struct_mutex); - - return convert_to_vm_err_msg(ret); -} - -int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* set vm_area_struct. */ - ret = drm_gem_mmap(filp, vma); - if (ret < 0) { - DRM_ERROR("failed to mmap.\n"); - return ret; - } - - vma->vm_flags &= ~VM_PFNMAP; - vma->vm_flags |= VM_MIXEDMAP; - - return ret; -} - - -int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, unsigned int handle) -{ - int ret; - - DRM_DEBUG_KMS("%s\n", __FILE__); - - /* - * obj->refcount and obj->handle_count are decreased and - * if both them are 0 then exynos_drm_gem_free_object() - * would be called by callback to release resources. - */ - ret = drm_gem_handle_delete(file_priv, handle); - if (ret < 0) { - DRM_ERROR("failed to delete drm_gem_handle.\n"); - return ret; - } - - return 0; -} - -MODULE_AUTHOR("Inki Dae "); -MODULE_DESCRIPTION("Samsung SoC DRM GEM Module"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.h deleted file mode 100644 index e5fc0148277b..000000000000 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ /dev/null @@ -1,107 +0,0 @@ -/* exynos_drm_gem.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authoer: Inki Dae - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_GEM_H_ -#define _EXYNOS_DRM_GEM_H_ - -#define to_exynos_gem_obj(x) container_of(x,\ - struct exynos_drm_gem_obj, base) - -/* - * exynos drm buffer structure. - * - * @base: a gem object. - * - a new handle to this gem object would be created - * by drm_gem_handle_create(). - * @entry: pointer to exynos drm buffer entry object. - * - containing the information to physically - * continuous memory region allocated by user request - * or at framebuffer creation. - * - * P.S. this object would be transfered to user as kms_bo.handle so - * user can access the buffer through kms_bo.handle. - */ -struct exynos_drm_gem_obj { - struct drm_gem_object base; - struct exynos_drm_buf_entry *entry; -}; - -/* create a new buffer and get a new gem handle. */ -struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv, - struct drm_device *dev, unsigned int size, - unsigned int *handle); - -/* - * request gem object creation and buffer allocation as the size - * that it is calculated with framebuffer information such as width, - * height and bpp. - */ -int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* get buffer offset to map to user space. */ -int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* unmap a buffer from user space. */ -int exynos_drm_gem_munmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* initialize gem object. */ -int exynos_drm_gem_init_object(struct drm_gem_object *obj); - -/* free gem object. */ -void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj); - -/* create memory region for drm framebuffer. */ -int exynos_drm_gem_dumb_create(struct drm_file *file_priv, - struct drm_device *dev, struct drm_mode_create_dumb *args); - -/* map memory region for drm framebuffer to user space. */ -int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, uint32_t handle, uint64_t *offset); - -/* page fault handler and mmap fault address(virtual) to physical memory. */ -int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); - -/* - * mmap the physically continuous memory that a gem object contains - * to user space. - */ -int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - -/* set vm_flags and we can change the vm attribute to other one at here. */ -int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); - -/* - * destroy memory region allocated. - * - a gem handle and physical memory region pointed by a gem object - * would be released by drm_gem_handle_delete(). - */ -int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv, - struct drm_device *dev, unsigned int handle); - -#endif diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index c829875ac63f..a685957566c9 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -4687,13 +4687,13 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, bpc = 6; /* min is 18bpp */ break; case 24: - bpc = min((unsigned int)8, display_bpc); + bpc = 8; break; case 30: - bpc = min((unsigned int)10, display_bpc); + bpc = 10; break; case 48: - bpc = min((unsigned int)12, display_bpc); + bpc = 12; break; default: DRM_DEBUG("unsupported depth, assuming 24 bits\n"); @@ -4701,10 +4701,12 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, break; } + display_bpc = min(display_bpc, bpc); + DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n", bpc, display_bpc); - *pipe_bpp = bpc * 3; + *pipe_bpp = display_bpc * 3; return display_bpc != bpc; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index ff5424e43d1b..0040d28816f1 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -102,7 +102,7 @@ extern int radeon_pcie_gen2; #define RADEON_FENCE_JIFFIES_TIMEOUT (HZ / 2) /* RADEON_IB_POOL_SIZE must be a power of 2 */ #define RADEON_IB_POOL_SIZE 16 -#define RADEON_DEBUGFS_MAX_COMPONENTS 32 +#define RADEON_DEBUGFS_MAX_NUM_FILES 32 #define RADEONFB_CONN_LIMIT 4 #define RADEON_BIOS_NUM_SCRATCH 8 diff --git a/trunk/drivers/gpu/drm/radeon/radeon_combios.c b/trunk/drivers/gpu/drm/radeon/radeon_combios.c index 8bf83c4b4147..63675241c7ff 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_combios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_combios.c @@ -620,8 +620,8 @@ static struct radeon_i2c_bus_rec combios_setup_i2c_bus(struct radeon_device *rde i2c.y_data_mask = 0x80; } else { /* default masks for ddc pads */ - i2c.mask_clk_mask = RADEON_GPIO_MASK_1; - i2c.mask_data_mask = RADEON_GPIO_MASK_0; + i2c.mask_clk_mask = RADEON_GPIO_EN_1; + i2c.mask_data_mask = RADEON_GPIO_EN_0; i2c.a_clk_mask = RADEON_GPIO_A_1; i2c.a_data_mask = RADEON_GPIO_A_0; i2c.en_clk_mask = RADEON_GPIO_EN_1; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c index 9b5b3e4d2386..c4b8741dbf58 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_connectors.c @@ -724,7 +724,6 @@ radeon_vga_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, radeon_connector->requires_extended_probe); if (dret) { - radeon_connector->detected_by_load = false; if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; @@ -751,21 +750,12 @@ radeon_vga_detect(struct drm_connector *connector, bool force) } else { /* if we aren't forcing don't do destructive polling */ - if (!force) { - /* only return the previous status if we last - * detected a monitor via load. - */ - if (radeon_connector->detected_by_load) - return connector->status; - else - return ret; - } + if (!force) + return connector->status; if (radeon_connector->dac_load_detect && encoder) { encoder_funcs = encoder->helper_private; ret = encoder_funcs->detect(encoder, connector); - if (ret == connector_status_connected) - radeon_connector->detected_by_load = true; } } @@ -907,7 +897,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) dret = radeon_ddc_probe(radeon_connector, radeon_connector->requires_extended_probe); if (dret) { - radeon_connector->detected_by_load = false; if (radeon_connector->edid) { kfree(radeon_connector->edid); radeon_connector->edid = NULL; @@ -970,18 +959,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if ((ret == connector_status_connected) && (radeon_connector->use_digital == true)) goto out; - /* DVI-D and HDMI-A are digital only */ - if ((connector->connector_type == DRM_MODE_CONNECTOR_DVID) || - (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)) - goto out; - - /* if we aren't forcing don't do destructive polling */ if (!force) { - /* only return the previous status if we last - * detected a monitor via load. - */ - if (radeon_connector->detected_by_load) - ret = connector->status; + ret = connector->status; goto out; } @@ -1005,7 +984,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ret = encoder_funcs->detect(encoder, connector); if (ret == connector_status_connected) { radeon_connector->use_digital = false; - radeon_connector->detected_by_load = true; } } break; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_device.c b/trunk/drivers/gpu/drm/radeon/radeon_device.c index cc695d05bd2b..b51e15725c6e 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_device.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_device.c @@ -750,15 +750,14 @@ int radeon_device_init(struct radeon_device *rdev, /* set DMA mask + need_dma32 flags. * PCIE - can handle 40-bits. - * IGP - can handle 40-bits + * IGP - can handle 40-bits (in theory) * AGP - generally dma32 is safest - * PCI - dma32 for legacy pci gart, 40 bits on newer asics + * PCI - only dma32 */ rdev->need_dma32 = false; if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; - if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family < CHIP_RS400)) + if (rdev->flags & RADEON_IS_PCI) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; @@ -982,7 +981,7 @@ struct radeon_debugfs { struct drm_info_list *files; unsigned num_files; }; -static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_COMPONENTS]; +static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES]; static unsigned _radeon_debugfs_count = 0; int radeon_debugfs_add_files(struct radeon_device *rdev, @@ -997,17 +996,14 @@ int radeon_debugfs_add_files(struct radeon_device *rdev, return 0; } } - - i = _radeon_debugfs_count + 1; - if (i > RADEON_DEBUGFS_MAX_COMPONENTS) { - DRM_ERROR("Reached maximum number of debugfs components.\n"); - DRM_ERROR("Report so we increase " - "RADEON_DEBUGFS_MAX_COMPONENTS.\n"); + if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) { + DRM_ERROR("Reached maximum number of debugfs files.\n"); + DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n"); return -EINVAL; } _radeon_debugfs[_radeon_debugfs_count].files = files; _radeon_debugfs[_radeon_debugfs_count].num_files = nfiles; - _radeon_debugfs_count = i; + _radeon_debugfs_count++; #if defined(CONFIG_DEBUG_FS) drm_debugfs_create_files(files, nfiles, rdev->ddev->control->debugfs_root, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_mode.h b/trunk/drivers/gpu/drm/radeon/radeon_mode.h index ed0178f03235..68820f5f6303 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_mode.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_mode.h @@ -447,7 +447,6 @@ struct radeon_connector { struct edid *edid; void *con_priv; bool dac_load_detect; - bool detected_by_load; /* if the connection status was determined by load */ uint16_t connector_object_id; struct radeon_hpd hpd; struct radeon_router router; diff --git a/trunk/drivers/gpu/drm/ttm/ttm_bo.c b/trunk/drivers/gpu/drm/ttm/ttm_bo.c index 6e96c85b70da..b824d9bdd87c 100644 --- a/trunk/drivers/gpu/drm/ttm/ttm_bo.c +++ b/trunk/drivers/gpu/drm/ttm/ttm_bo.c @@ -1295,7 +1295,6 @@ int ttm_bo_create(struct ttm_bo_device *bdev, return ret; } -EXPORT_SYMBOL(ttm_bo_create); static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, unsigned mem_type, bool allow_errors) diff --git a/trunk/drivers/gpu/drm/vmwgfx/Makefile b/trunk/drivers/gpu/drm/vmwgfx/Makefile index 586869c8c11f..7d8e9d5d498c 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/Makefile +++ b/trunk/drivers/gpu/drm/vmwgfx/Makefile @@ -5,6 +5,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_fb.o vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_buffer.o \ vmwgfx_fifo.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \ vmwgfx_overlay.o vmwgfx_marker.o vmwgfx_gmrid_manager.o \ - vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o + vmwgfx_fence.o obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o diff --git a/trunk/drivers/gpu/drm/vmwgfx/svga3d_reg.h b/trunk/drivers/gpu/drm/vmwgfx/svga3d_reg.h index d0e085ee8249..77cb45331000 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/svga3d_reg.h +++ b/trunk/drivers/gpu/drm/vmwgfx/svga3d_reg.h @@ -57,8 +57,7 @@ typedef enum { SVGA3D_HWVERSION_WS6_B1 = SVGA3D_MAKE_HWVERSION(1, 1), SVGA3D_HWVERSION_FUSION_11 = SVGA3D_MAKE_HWVERSION(1, 4), SVGA3D_HWVERSION_WS65_B1 = SVGA3D_MAKE_HWVERSION(2, 0), - SVGA3D_HWVERSION_WS8_B1 = SVGA3D_MAKE_HWVERSION(2, 1), - SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS8_B1, + SVGA3D_HWVERSION_CURRENT = SVGA3D_HWVERSION_WS65_B1, } SVGA3dHardwareVersion; /* @@ -68,8 +67,7 @@ typedef enum { typedef uint32 SVGA3dBool; /* 32-bit Bool definition */ #define SVGA3D_NUM_CLIPPLANES 6 #define SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS 8 -#define SVGA3D_MAX_CONTEXT_IDS 256 -#define SVGA3D_MAX_SURFACE_IDS (32 * 1024) + /* * Surface formats. @@ -81,91 +79,76 @@ typedef uint32 SVGA3dBool; /* 32-bit Bool definition */ */ typedef enum SVGA3dSurfaceFormat { - SVGA3D_FORMAT_INVALID = 0, + SVGA3D_FORMAT_INVALID = 0, - SVGA3D_X8R8G8B8 = 1, - SVGA3D_A8R8G8B8 = 2, + SVGA3D_X8R8G8B8 = 1, + SVGA3D_A8R8G8B8 = 2, - SVGA3D_R5G6B5 = 3, - SVGA3D_X1R5G5B5 = 4, - SVGA3D_A1R5G5B5 = 5, - SVGA3D_A4R4G4B4 = 6, + SVGA3D_R5G6B5 = 3, + SVGA3D_X1R5G5B5 = 4, + SVGA3D_A1R5G5B5 = 5, + SVGA3D_A4R4G4B4 = 6, - SVGA3D_Z_D32 = 7, - SVGA3D_Z_D16 = 8, - SVGA3D_Z_D24S8 = 9, - SVGA3D_Z_D15S1 = 10, + SVGA3D_Z_D32 = 7, + SVGA3D_Z_D16 = 8, + SVGA3D_Z_D24S8 = 9, + SVGA3D_Z_D15S1 = 10, - SVGA3D_LUMINANCE8 = 11, - SVGA3D_LUMINANCE4_ALPHA4 = 12, - SVGA3D_LUMINANCE16 = 13, - SVGA3D_LUMINANCE8_ALPHA8 = 14, + SVGA3D_LUMINANCE8 = 11, + SVGA3D_LUMINANCE4_ALPHA4 = 12, + SVGA3D_LUMINANCE16 = 13, + SVGA3D_LUMINANCE8_ALPHA8 = 14, - SVGA3D_DXT1 = 15, - SVGA3D_DXT2 = 16, - SVGA3D_DXT3 = 17, - SVGA3D_DXT4 = 18, - SVGA3D_DXT5 = 19, + SVGA3D_DXT1 = 15, + SVGA3D_DXT2 = 16, + SVGA3D_DXT3 = 17, + SVGA3D_DXT4 = 18, + SVGA3D_DXT5 = 19, - SVGA3D_BUMPU8V8 = 20, - SVGA3D_BUMPL6V5U5 = 21, - SVGA3D_BUMPX8L8V8U8 = 22, - SVGA3D_BUMPL8V8U8 = 23, + SVGA3D_BUMPU8V8 = 20, + SVGA3D_BUMPL6V5U5 = 21, + SVGA3D_BUMPX8L8V8U8 = 22, + SVGA3D_BUMPL8V8U8 = 23, - SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */ - SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */ + SVGA3D_ARGB_S10E5 = 24, /* 16-bit floating-point ARGB */ + SVGA3D_ARGB_S23E8 = 25, /* 32-bit floating-point ARGB */ - SVGA3D_A2R10G10B10 = 26, + SVGA3D_A2R10G10B10 = 26, /* signed formats */ - SVGA3D_V8U8 = 27, - SVGA3D_Q8W8V8U8 = 28, - SVGA3D_CxV8U8 = 29, + SVGA3D_V8U8 = 27, + SVGA3D_Q8W8V8U8 = 28, + SVGA3D_CxV8U8 = 29, /* mixed formats */ - SVGA3D_X8L8V8U8 = 30, - SVGA3D_A2W10V10U10 = 31, + SVGA3D_X8L8V8U8 = 30, + SVGA3D_A2W10V10U10 = 31, - SVGA3D_ALPHA8 = 32, + SVGA3D_ALPHA8 = 32, /* Single- and dual-component floating point formats */ - SVGA3D_R_S10E5 = 33, - SVGA3D_R_S23E8 = 34, - SVGA3D_RG_S10E5 = 35, - SVGA3D_RG_S23E8 = 36, + SVGA3D_R_S10E5 = 33, + SVGA3D_R_S23E8 = 34, + SVGA3D_RG_S10E5 = 35, + SVGA3D_RG_S23E8 = 36, /* * Any surface can be used as a buffer object, but SVGA3D_BUFFER is * the most efficient format to use when creating new surfaces * expressly for index or vertex data. */ + SVGA3D_BUFFER = 37, - SVGA3D_BUFFER = 37, - - SVGA3D_Z_D24X8 = 38, + SVGA3D_Z_D24X8 = 38, - SVGA3D_V16U16 = 39, + SVGA3D_V16U16 = 39, - SVGA3D_G16R16 = 40, - SVGA3D_A16B16G16R16 = 41, + SVGA3D_G16R16 = 40, + SVGA3D_A16B16G16R16 = 41, /* Packed Video formats */ - SVGA3D_UYVY = 42, - SVGA3D_YUY2 = 43, - - /* Planar video formats */ - SVGA3D_NV12 = 44, - - /* Video format with alpha */ - SVGA3D_AYUV = 45, - - SVGA3D_BC4_UNORM = 108, - SVGA3D_BC5_UNORM = 111, - - /* Advanced D3D9 depth formats. */ - SVGA3D_Z_DF16 = 118, - SVGA3D_Z_DF24 = 119, - SVGA3D_Z_D24S8_INT = 120, + SVGA3D_UYVY = 42, + SVGA3D_YUY2 = 43, SVGA3D_FORMAT_MAX } SVGA3dSurfaceFormat; @@ -431,19 +414,9 @@ typedef enum { SVGA3D_RS_SRCBLENDALPHA = 94, /* SVGA3dBlendOp */ SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */ SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */ - SVGA3D_RS_TRANSPARENCYANTIALIAS = 97, /* SVGA3dTransparencyAntialiasType */ - SVGA3D_RS_LINEAA = 98, /* SVGA3dBool */ - SVGA3D_RS_LINEWIDTH = 99, /* float */ SVGA3D_RS_MAX } SVGA3dRenderStateName; -typedef enum { - SVGA3D_TRANSPARENCYANTIALIAS_NORMAL = 0, - SVGA3D_TRANSPARENCYANTIALIAS_ALPHATOCOVERAGE = 1, - SVGA3D_TRANSPARENCYANTIALIAS_SUPERSAMPLE = 2, - SVGA3D_TRANSPARENCYANTIALIAS_MAX -} SVGA3dTransparencyAntialiasType; - typedef enum { SVGA3D_VERTEXMATERIAL_NONE = 0, /* Use the value in the current material */ SVGA3D_VERTEXMATERIAL_DIFFUSE = 1, /* Use the value in the diffuse component */ @@ -755,10 +728,10 @@ typedef enum { SVGA3D_TEX_FILTER_NEAREST = 1, SVGA3D_TEX_FILTER_LINEAR = 2, SVGA3D_TEX_FILTER_ANISOTROPIC = 3, - SVGA3D_TEX_FILTER_FLATCUBIC = 4, /* Deprecated, not implemented */ - SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, /* Deprecated, not implemented */ - SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, /* Not currently implemented */ - SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, /* Not currently implemented */ + SVGA3D_TEX_FILTER_FLATCUBIC = 4, // Deprecated, not implemented + SVGA3D_TEX_FILTER_GAUSSIANCUBIC = 5, // Deprecated, not implemented + SVGA3D_TEX_FILTER_PYRAMIDALQUAD = 6, // Not currently implemented + SVGA3D_TEX_FILTER_GAUSSIANQUAD = 7, // Not currently implemented SVGA3D_TEX_FILTER_MAX } SVGA3dTextureFilter; @@ -826,19 +799,19 @@ typedef enum { typedef enum { SVGA3D_DECLUSAGE_POSITION = 0, - SVGA3D_DECLUSAGE_BLENDWEIGHT, /* 1 */ - SVGA3D_DECLUSAGE_BLENDINDICES, /* 2 */ - SVGA3D_DECLUSAGE_NORMAL, /* 3 */ - SVGA3D_DECLUSAGE_PSIZE, /* 4 */ - SVGA3D_DECLUSAGE_TEXCOORD, /* 5 */ - SVGA3D_DECLUSAGE_TANGENT, /* 6 */ - SVGA3D_DECLUSAGE_BINORMAL, /* 7 */ - SVGA3D_DECLUSAGE_TESSFACTOR, /* 8 */ - SVGA3D_DECLUSAGE_POSITIONT, /* 9 */ - SVGA3D_DECLUSAGE_COLOR, /* 10 */ - SVGA3D_DECLUSAGE_FOG, /* 11 */ - SVGA3D_DECLUSAGE_DEPTH, /* 12 */ - SVGA3D_DECLUSAGE_SAMPLE, /* 13 */ + SVGA3D_DECLUSAGE_BLENDWEIGHT, // 1 + SVGA3D_DECLUSAGE_BLENDINDICES, // 2 + SVGA3D_DECLUSAGE_NORMAL, // 3 + SVGA3D_DECLUSAGE_PSIZE, // 4 + SVGA3D_DECLUSAGE_TEXCOORD, // 5 + SVGA3D_DECLUSAGE_TANGENT, // 6 + SVGA3D_DECLUSAGE_BINORMAL, // 7 + SVGA3D_DECLUSAGE_TESSFACTOR, // 8 + SVGA3D_DECLUSAGE_POSITIONT, // 9 + SVGA3D_DECLUSAGE_COLOR, // 10 + SVGA3D_DECLUSAGE_FOG, // 11 + SVGA3D_DECLUSAGE_DEPTH, // 12 + SVGA3D_DECLUSAGE_SAMPLE, // 13 SVGA3D_DECLUSAGE_MAX } SVGA3dDeclUsage; @@ -846,10 +819,10 @@ typedef enum { SVGA3D_DECLMETHOD_DEFAULT = 0, SVGA3D_DECLMETHOD_PARTIALU, SVGA3D_DECLMETHOD_PARTIALV, - SVGA3D_DECLMETHOD_CROSSUV, /* Normal */ + SVGA3D_DECLMETHOD_CROSSUV, // Normal SVGA3D_DECLMETHOD_UV, - SVGA3D_DECLMETHOD_LOOKUP, /* Lookup a displacement map */ - SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, /* Lookup a pre-sampled displacement map */ + SVGA3D_DECLMETHOD_LOOKUP, // Lookup a displacement map + SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map } SVGA3dDeclMethod; typedef enum { @@ -957,6 +930,7 @@ typedef enum { } SVGA3dCubeFace; typedef enum { + SVGA3D_SHADERTYPE_COMPILED_DX8 = 0, SVGA3D_SHADERTYPE_VS = 1, SVGA3D_SHADERTYPE_PS = 2, SVGA3D_SHADERTYPE_MAX @@ -994,17 +968,11 @@ typedef enum { } SVGA3dTransferType; /* - * The maximum number of vertex arrays we're guaranteed to support in + * The maximum number vertex arrays we're guaranteed to support in * SVGA_3D_CMD_DRAWPRIMITIVES. */ #define SVGA3D_MAX_VERTEX_ARRAYS 32 -/* - * The maximum number of primitive ranges we're guaranteed to support - * in SVGA_3D_CMD_DRAWPRIMITIVES. - */ -#define SVGA3D_MAX_DRAW_PRIMITIVE_RANGES 32 - /* * Identifiers for commands in the command FIFO. * @@ -1022,7 +990,7 @@ typedef enum { #define SVGA_3D_CMD_LEGACY_BASE 1000 #define SVGA_3D_CMD_BASE 1040 -#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0 /* Deprecated */ +#define SVGA_3D_CMD_SURFACE_DEFINE SVGA_3D_CMD_BASE + 0 #define SVGA_3D_CMD_SURFACE_DESTROY SVGA_3D_CMD_BASE + 1 #define SVGA_3D_CMD_SURFACE_COPY SVGA_3D_CMD_BASE + 2 #define SVGA_3D_CMD_SURFACE_STRETCHBLT SVGA_3D_CMD_BASE + 3 @@ -1040,7 +1008,7 @@ typedef enum { #define SVGA_3D_CMD_SETVIEWPORT SVGA_3D_CMD_BASE + 15 #define SVGA_3D_CMD_SETCLIPPLANE SVGA_3D_CMD_BASE + 16 #define SVGA_3D_CMD_CLEAR SVGA_3D_CMD_BASE + 17 -#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 /* Deprecated */ +#define SVGA_3D_CMD_PRESENT SVGA_3D_CMD_BASE + 18 // Deprecated #define SVGA_3D_CMD_SHADER_DEFINE SVGA_3D_CMD_BASE + 19 #define SVGA_3D_CMD_SHADER_DESTROY SVGA_3D_CMD_BASE + 20 #define SVGA_3D_CMD_SET_SHADER SVGA_3D_CMD_BASE + 21 @@ -1050,13 +1018,9 @@ typedef enum { #define SVGA_3D_CMD_BEGIN_QUERY SVGA_3D_CMD_BASE + 25 #define SVGA_3D_CMD_END_QUERY SVGA_3D_CMD_BASE + 26 #define SVGA_3D_CMD_WAIT_FOR_QUERY SVGA_3D_CMD_BASE + 27 -#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 /* Deprecated */ +#define SVGA_3D_CMD_PRESENT_READBACK SVGA_3D_CMD_BASE + 28 // Deprecated #define SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN SVGA_3D_CMD_BASE + 29 -#define SVGA_3D_CMD_SURFACE_DEFINE_V2 SVGA_3D_CMD_BASE + 30 -#define SVGA_3D_CMD_GENERATE_MIPMAPS SVGA_3D_CMD_BASE + 31 -#define SVGA_3D_CMD_ACTIVATE_SURFACE SVGA_3D_CMD_BASE + 40 -#define SVGA_3D_CMD_DEACTIVATE_SURFACE SVGA_3D_CMD_BASE + 41 -#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 42 +#define SVGA_3D_CMD_MAX SVGA_3D_CMD_BASE + 30 #define SVGA_3D_CMD_FUTURE_MAX 2000 @@ -1067,9 +1031,9 @@ typedef enum { typedef struct { union { struct { - uint16 function; /* SVGA3dFogFunction */ - uint8 type; /* SVGA3dFogType */ - uint8 base; /* SVGA3dFogBase */ + uint16 function; // SVGA3dFogFunction + uint8 type; // SVGA3dFogType + uint8 base; // SVGA3dFogBase }; uint32 uintValue; }; @@ -1145,8 +1109,6 @@ typedef enum { SVGA3D_SURFACE_HINT_RENDERTARGET = (1 << 6), SVGA3D_SURFACE_HINT_DEPTHSTENCIL = (1 << 7), SVGA3D_SURFACE_HINT_WRITEONLY = (1 << 8), - SVGA3D_SURFACE_MASKABLE_ANTIALIAS = (1 << 9), - SVGA3D_SURFACE_AUTOGENMIPMAPS = (1 << 10), } SVGA3dSurfaceFlags; typedef @@ -1159,12 +1121,6 @@ struct { uint32 sid; SVGA3dSurfaceFlags surfaceFlags; SVGA3dSurfaceFormat format; - /* - * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace - * structures must have the same value of numMipLevels field. - * Otherwise, all but the first SVGA3dSurfaceFace structures must have the - * numMipLevels set to 0. - */ SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES]; /* * Followed by an SVGA3dSize structure for each mip level in each face. @@ -1177,31 +1133,6 @@ struct { */ } SVGA3dCmdDefineSurface; /* SVGA_3D_CMD_SURFACE_DEFINE */ -typedef -struct { - uint32 sid; - SVGA3dSurfaceFlags surfaceFlags; - SVGA3dSurfaceFormat format; - /* - * If surfaceFlags has SVGA3D_SURFACE_CUBEMAP bit set, all SVGA3dSurfaceFace - * structures must have the same value of numMipLevels field. - * Otherwise, all but the first SVGA3dSurfaceFace structures must have the - * numMipLevels set to 0. - */ - SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES]; - uint32 multisampleCount; - SVGA3dTextureFilter autogenFilter; - /* - * Followed by an SVGA3dSize structure for each mip level in each face. - * - * A note on surface sizes: Sizes are always specified in pixels, - * even if the true surface size is not a multiple of the minimum - * block size of the surface's format. For example, a 3x3x1 DXT1 - * compressed texture would actually be stored as a 4x4x1 image in - * memory. - */ -} SVGA3dCmdDefineSurface_v2; /* SVGA_3D_CMD_SURFACE_DEFINE_V2 */ - typedef struct { uint32 sid; @@ -1543,12 +1474,10 @@ struct { * SVGA3dCmdDrawPrimitives structure. In order, * they are: * - * 1. SVGA3dVertexDecl, quantity 'numVertexDecls', but no more than - * SVGA3D_MAX_VERTEX_ARRAYS; - * 2. SVGA3dPrimitiveRange, quantity 'numRanges', but no more than - * SVGA3D_MAX_DRAW_PRIMITIVE_RANGES; + * 1. SVGA3dVertexDecl, quantity 'numVertexDecls' + * 2. SVGA3dPrimitiveRange, quantity 'numRanges' * 3. Optionally, SVGA3dVertexDivisor, quantity 'numVertexDecls' (contains - * the frequency divisor for the corresponding vertex decl). + * the frequency divisor for this the corresponding vertex decl) */ } SVGA3dCmdDrawPrimitives; /* SVGA_3D_CMD_DRAWPRIMITIVES */ @@ -1742,12 +1671,6 @@ struct { /* Clipping: zero or more SVGASignedRects follow */ } SVGA3dCmdBlitSurfaceToScreen; /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */ -typedef -struct { - uint32 sid; - SVGA3dTextureFilter filter; -} SVGA3dCmdGenerateMipmaps; /* SVGA_3D_CMD_GENERATE_MIPMAPS */ - /* * Capability query index. @@ -1851,32 +1774,6 @@ typedef enum { SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = 67, SVGA3D_DEVCAP_SURFACEFMT_UYVY = 68, SVGA3D_DEVCAP_SURFACEFMT_YUY2 = 69, - SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = 70, - SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = 71, - SVGA3D_DEVCAP_ALPHATOCOVERAGE = 72, - SVGA3D_DEVCAP_SUPERSAMPLE = 73, - SVGA3D_DEVCAP_AUTOGENMIPMAPS = 74, - SVGA3D_DEVCAP_SURFACEFMT_NV12 = 75, - SVGA3D_DEVCAP_SURFACEFMT_AYUV = 76, - - /* - * This is the maximum number of SVGA context IDs that the guest - * can define using SVGA_3D_CMD_CONTEXT_DEFINE. - */ - SVGA3D_DEVCAP_MAX_CONTEXT_IDS = 77, - - /* - * This is the maximum number of SVGA surface IDs that the guest - * can define using SVGA_3D_CMD_SURFACE_DEFINE*. - */ - SVGA3D_DEVCAP_MAX_SURFACE_IDS = 78, - - SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = 79, - SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = 80, - SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = 81, - - SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = 82, - SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = 83, /* * Don't add new caps into the previous section; the values in this diff --git a/trunk/drivers/gpu/drm/vmwgfx/svga_escape.h b/trunk/drivers/gpu/drm/vmwgfx/svga_escape.h index 8e8d9682e018..7b85e9b8c854 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/svga_escape.h +++ b/trunk/drivers/gpu/drm/vmwgfx/svga_escape.h @@ -75,7 +75,7 @@ */ #define SVGA_ESCAPE_VMWARE_HINT 0x00030000 -#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 /* Deprecated */ +#define SVGA_ESCAPE_VMWARE_HINT_FULLSCREEN 0x00030001 // Deprecated typedef struct { diff --git a/trunk/drivers/gpu/drm/vmwgfx/svga_overlay.h b/trunk/drivers/gpu/drm/vmwgfx/svga_overlay.h index f38416fcb046..f753d73c14b4 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/svga_overlay.h +++ b/trunk/drivers/gpu/drm/vmwgfx/svga_overlay.h @@ -38,9 +38,9 @@ * Video formats we support */ -#define VMWARE_FOURCC_YV12 0x32315659 /* 'Y' 'V' '1' '2' */ -#define VMWARE_FOURCC_YUY2 0x32595559 /* 'Y' 'U' 'Y' '2' */ -#define VMWARE_FOURCC_UYVY 0x59565955 /* 'U' 'Y' 'V' 'Y' */ +#define VMWARE_FOURCC_YV12 0x32315659 // 'Y' 'V' '1' '2' +#define VMWARE_FOURCC_YUY2 0x32595559 // 'Y' 'U' 'Y' '2' +#define VMWARE_FOURCC_UYVY 0x59565955 // 'U' 'Y' 'V' 'Y' typedef enum { SVGA_OVERLAY_FORMAT_INVALID = 0, @@ -68,7 +68,7 @@ struct SVGAEscapeVideoSetRegs { uint32 streamId; } header; - /* May include zero or more items. */ + // May include zero or more items. struct { uint32 registerId; uint32 value; @@ -134,12 +134,12 @@ struct { */ static inline bool -VMwareVideoGetAttributes(const SVGAOverlayFormat format, /* IN */ - uint32 *width, /* IN / OUT */ - uint32 *height, /* IN / OUT */ - uint32 *size, /* OUT */ - uint32 *pitches, /* OUT (optional) */ - uint32 *offsets) /* OUT (optional) */ +VMwareVideoGetAttributes(const SVGAOverlayFormat format, // IN + uint32 *width, // IN / OUT + uint32 *height, // IN / OUT + uint32 *size, // OUT + uint32 *pitches, // OUT (optional) + uint32 *offsets) // OUT (optional) { int tmp; @@ -198,4 +198,4 @@ VMwareVideoGetAttributes(const SVGAOverlayFormat format, /* IN */ return true; } -#endif /* _SVGA_OVERLAY_H_ */ +#endif // _SVGA_OVERLAY_H_ diff --git a/trunk/drivers/gpu/drm/vmwgfx/svga_reg.h b/trunk/drivers/gpu/drm/vmwgfx/svga_reg.h index 01f63cb49678..ec5aad9b6ed3 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/svga_reg.h +++ b/trunk/drivers/gpu/drm/vmwgfx/svga_reg.h @@ -276,7 +276,7 @@ enum { * possible. */ #define SVGA_GMR_NULL ((uint32) -1) -#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */ +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) // Guest Framebuffer (GFB) typedef struct SVGAGuestMemDescriptor { @@ -317,35 +317,13 @@ struct SVGAGMRImageFormat { struct { uint32 bitsPerPixel : 8; uint32 colorDepth : 8; - uint32 reserved : 16; /* Must be zero */ + uint32 reserved : 16; // Must be zero }; uint32 value; }; } SVGAGMRImageFormat; -typedef -struct SVGAGuestImage { - SVGAGuestPtr ptr; - - /* - * A note on interpretation of pitch: This value of pitch is the - * number of bytes between vertically adjacent image - * blocks. Normally this is the number of bytes between the first - * pixel of two adjacent scanlines. With compressed textures, - * however, this may represent the number of bytes between - * compression blocks rather than between rows of pixels. - * - * XXX: Compressed textures currently must be tightly packed in guest memory. - * - * If the image is 1-dimensional, pitch is ignored. - * - * If 'pitch' is zero, the SVGA3D device calculates a pitch value - * assuming each row of blocks is tightly packed. - */ - uint32 pitch; -} SVGAGuestImage; - /* * SVGAColorBGRX -- * @@ -361,7 +339,7 @@ struct SVGAColorBGRX { uint32 b : 8; uint32 g : 8; uint32 r : 8; - uint32 x : 8; /* Unused */ + uint32 x : 8; // Unused }; uint32 value; @@ -417,16 +395,16 @@ struct SVGASignedPoint { #define SVGA_CAP_NONE 0x00000000 #define SVGA_CAP_RECT_COPY 0x00000002 #define SVGA_CAP_CURSOR 0x00000020 -#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */ -#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_CURSOR_BYPASS 0x00000040 // Legacy (Use Cursor Bypass 3 instead) +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 // Legacy (Use Cursor Bypass 3 instead) #define SVGA_CAP_8BIT_EMULATION 0x00000100 #define SVGA_CAP_ALPHA_CURSOR 0x00000200 #define SVGA_CAP_3D 0x00004000 #define SVGA_CAP_EXTENDED_FIFO 0x00008000 -#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */ +#define SVGA_CAP_MULTIMON 0x00010000 // Legacy multi-monitor support #define SVGA_CAP_PITCHLOCK 0x00020000 #define SVGA_CAP_IRQMASK 0x00040000 -#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */ +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 // Legacy multi-monitor support #define SVGA_CAP_GMR 0x00100000 #define SVGA_CAP_TRACES 0x00200000 #define SVGA_CAP_GMR2 0x00400000 @@ -475,7 +453,7 @@ enum { SVGA_FIFO_CAPABILITIES = 4, SVGA_FIFO_FLAGS, - /* Valid with SVGA_FIFO_CAP_FENCE: */ + // Valid with SVGA_FIFO_CAP_FENCE: SVGA_FIFO_FENCE, /* @@ -488,46 +466,32 @@ enum { * extended FIFO. */ - /* Valid if exists (i.e. if extended FIFO enabled): */ + // Valid if exists (i.e. if extended FIFO enabled): SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ - /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ + // Valid with SVGA_FIFO_CAP_PITCHLOCK: SVGA_FIFO_PITCHLOCK, - /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ + // Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ - /* Valid with SVGA_FIFO_CAP_RESERVE: */ + // Valid with SVGA_FIFO_CAP_RESERVE: SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ /* - * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2: + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT: * * By default this is SVGA_ID_INVALID, to indicate that the cursor * coordinates are specified relative to the virtual root. If this * is set to a specific screen ID, cursor position is reinterpreted - * as a signed offset relative to that screen's origin. + * as a signed offset relative to that screen's origin. This is the + * only way to place the cursor on a non-rooted screen. */ SVGA_FIFO_CURSOR_SCREEN_ID, - /* - * Valid with SVGA_FIFO_CAP_DEAD - * - * An arbitrary value written by the host, drivers should not use it. - */ - SVGA_FIFO_DEAD, - - /* - * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED: - * - * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h) - * on platforms that can enforce graphics resource limits. - */ - SVGA_FIFO_3D_HWVERSION_REVISED, - /* * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new * registers, but this must be done carefully and with judicious use of @@ -566,7 +530,7 @@ enum { * sets SVGA_FIFO_MIN high enough to leave room for them. */ - /* Valid if register exists: */ + // Valid if register exists: SVGA_FIFO_GUEST_3D_HWVERSION, /* Guest driver's 3D version */ SVGA_FIFO_FENCE_GOAL, /* Matching target for SVGA_IRQFLAG_FENCE_GOAL */ SVGA_FIFO_BUSY, /* See "FIFO Synchronization Registers" */ @@ -767,37 +731,6 @@ enum { * * - When a screen is resized, either using Screen Object commands or * legacy multimon registers, its contents are preserved. - * - * SVGA_FIFO_CAP_GMR2 -- - * - * Provides new commands to define and remap guest memory regions (GMR). - * - * New 2D commands: - * DEFINE_GMR2, REMAP_GMR2. - * - * SVGA_FIFO_CAP_3D_HWVERSION_REVISED -- - * - * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists. - * This register may replace SVGA_FIFO_3D_HWVERSION on platforms - * that enforce graphics resource limits. This allows the platform - * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest - * drivers that do not limit their resources. - * - * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators - * are codependent (and thus we use a single capability bit). - * - * SVGA_FIFO_CAP_SCREEN_OBJECT_2 -- - * - * Modifies the DEFINE_SCREEN command to include a guest provided - * backing store in GMR memory and the bytesPerLine for the backing - * store. This capability requires the use of a backing store when - * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT - * is present then backing stores are optional. - * - * SVGA_FIFO_CAP_DEAD -- - * - * Drivers should not use this cap bit. This cap bit can not be - * reused since some hosts already expose it. */ #define SVGA_FIFO_CAP_NONE 0 @@ -809,10 +742,6 @@ enum { #define SVGA_FIFO_CAP_ESCAPE (1<<5) #define SVGA_FIFO_CAP_RESERVE (1<<6) #define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) -#define SVGA_FIFO_CAP_GMR2 (1<<8) -#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2 -#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9) -#define SVGA_FIFO_CAP_DEAD (1<<10) /* @@ -823,7 +752,7 @@ enum { #define SVGA_FIFO_FLAG_NONE 0 #define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) -#define SVGA_FIFO_FLAG_RESERVED (1<<31) /* Internal use only */ +#define SVGA_FIFO_FLAG_RESERVED (1<<31) // Internal use only /* * FIFO reservation sentinel value @@ -856,22 +785,22 @@ enum { SVGA_VIDEO_DATA_OFFSET, SVGA_VIDEO_FORMAT, SVGA_VIDEO_COLORKEY, - SVGA_VIDEO_SIZE, /* Deprecated */ + SVGA_VIDEO_SIZE, // Deprecated SVGA_VIDEO_WIDTH, SVGA_VIDEO_HEIGHT, SVGA_VIDEO_SRC_X, SVGA_VIDEO_SRC_Y, SVGA_VIDEO_SRC_WIDTH, SVGA_VIDEO_SRC_HEIGHT, - SVGA_VIDEO_DST_X, /* Signed int32 */ - SVGA_VIDEO_DST_Y, /* Signed int32 */ + SVGA_VIDEO_DST_X, // Signed int32 + SVGA_VIDEO_DST_Y, // Signed int32 SVGA_VIDEO_DST_WIDTH, SVGA_VIDEO_DST_HEIGHT, SVGA_VIDEO_PITCH_1, SVGA_VIDEO_PITCH_2, SVGA_VIDEO_PITCH_3, - SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */ - SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */ + SVGA_VIDEO_DATA_GMRID, // Optional, defaults to SVGA_GMR_FRAMEBUFFER + SVGA_VIDEO_DST_SCREEN_ID, // Optional, defaults to virtual coords (SVGA_ID_INVALID) SVGA_VIDEO_NUM_REGS }; @@ -922,51 +851,15 @@ typedef struct SVGAOverlayUnit { * compatibility. New flags can be added, and the struct may grow, * but existing fields must retain their meaning. * - * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of - * a SVGAGuestPtr that is used to back the screen contents. This - * memory must come from the GFB. The guest is not allowed to - * access the memory and doing so will have undefined results. The - * backing store is required to be page aligned and the size is - * padded to the next page boundry. The number of pages is: - * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE - * - * The pitch in the backingStore is required to be at least large - * enough to hold a 32bbp scanline. It is recommended that the - * driver pad bytesPerLine for a potential performance win. - * - * The cloneCount field is treated as a hint from the guest that - * the user wants this display to be cloned, countCount times. A - * value of zero means no cloning should happen. */ -#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */ -#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */ -#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */ -#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */ - -/* - * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is - * deactivated the base layer is defined to lose all contents and - * become black. When a screen is deactivated the backing store is - * optional. When set backingPtr and bytesPerLine will be ignored. - */ -#define SVGA_SCREEN_DEACTIVATE (1 << 3) - -/* - * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set - * the screen contents will be outputted as all black to the user - * though the base layer contents is preserved. The screen base layer - * can still be read and written to like normal though the no visible - * effect will be seen by the user. When the flag is changed the - * screen will be blanked or redrawn to the current contents as needed - * without any extra commands from the driver. This flag only has an - * effect when the screen is not deactivated. - */ -#define SVGA_SCREEN_BLANKING (1 << 4) +#define SVGA_SCREEN_HAS_ROOT (1 << 0) // Screen is present in the virtual coord space +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) // Guest considers this screen to be 'primary' +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) // Guest is running a fullscreen app here typedef struct SVGAScreenObject { - uint32 structSize; /* sizeof(SVGAScreenObject) */ + uint32 structSize; // sizeof(SVGAScreenObject) uint32 id; uint32 flags; struct { @@ -976,14 +869,7 @@ struct SVGAScreenObject { struct { int32 x; int32 y; - } root; - - /* - * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional - * with SVGA_FIFO_CAP_SCREEN_OBJECT. - */ - SVGAGuestImage backingStore; - uint32 cloneCount; + } root; // Only used if SVGA_SCREEN_HAS_ROOT is set. } SVGAScreenObject; @@ -1058,7 +944,7 @@ typedef enum { */ typedef -struct SVGAFifoCmdUpdate { +struct { uint32 x; uint32 y; uint32 width; @@ -1077,7 +963,7 @@ struct SVGAFifoCmdUpdate { */ typedef -struct SVGAFifoCmdRectCopy { +struct { uint32 srcX; uint32 srcY; uint32 destX; @@ -1101,14 +987,14 @@ struct SVGAFifoCmdRectCopy { */ typedef -struct SVGAFifoCmdDefineCursor { - uint32 id; /* Reserved, must be zero. */ +struct { + uint32 id; // Reserved, must be zero. uint32 hotspotX; uint32 hotspotY; uint32 width; uint32 height; - uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ - uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + uint32 andMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL + uint32 xorMaskDepth; // Value must be 1 or equal to BITS_PER_PIXEL /* * Followed by scanline data for AND mask, then XOR mask. * Each scanline is padded to a 32-bit boundary. @@ -1130,8 +1016,8 @@ struct SVGAFifoCmdDefineCursor { */ typedef -struct SVGAFifoCmdDefineAlphaCursor { - uint32 id; /* Reserved, must be zero. */ +struct { + uint32 id; // Reserved, must be zero. uint32 hotspotX; uint32 hotspotY; uint32 width; @@ -1153,7 +1039,7 @@ struct SVGAFifoCmdDefineAlphaCursor { */ typedef -struct SVGAFifoCmdUpdateVerbose { +struct { uint32 x; uint32 y; uint32 width; @@ -1178,13 +1064,13 @@ struct SVGAFifoCmdUpdateVerbose { #define SVGA_ROP_COPY 0x03 typedef -struct SVGAFifoCmdFrontRopFill { - uint32 color; /* In the same format as the GFB */ +struct { + uint32 color; // In the same format as the GFB uint32 x; uint32 y; uint32 width; uint32 height; - uint32 rop; /* Must be SVGA_ROP_COPY */ + uint32 rop; // Must be SVGA_ROP_COPY } SVGAFifoCmdFrontRopFill; @@ -1221,7 +1107,7 @@ struct { */ typedef -struct SVGAFifoCmdEscape { +struct { uint32 nsid; uint32 size; /* followed by 'size' bytes of data */ @@ -1251,12 +1137,12 @@ struct SVGAFifoCmdEscape { * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef struct { - SVGAScreenObject screen; /* Variable-length according to version */ + SVGAScreenObject screen; // Variable-length according to version } SVGAFifoCmdDefineScreen; @@ -1267,7 +1153,7 @@ struct { * re-use. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1320,7 +1206,7 @@ struct { * GMRFB. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1357,7 +1243,7 @@ struct { * SVGA_CMD_ANNOTATION_* commands for details. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1405,7 +1291,7 @@ struct { * the time any subsequent FENCE commands are reached. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1440,7 +1326,7 @@ struct { * user's display is being remoted over a network connection. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1472,7 +1358,7 @@ struct { * undefined. * * Availability: - * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + * SVGA_FIFO_CAP_SCREEN_OBJECT */ typedef @@ -1495,7 +1381,8 @@ typedef struct { uint32 gmrId; uint32 numPages; -} SVGAFifoCmdDefineGMR2; +} +SVGAFifoCmdDefineGMR2; /* @@ -1537,8 +1424,8 @@ typedef struct { uint32 gmrId; SVGARemapGMR2Flags flags; - uint32 offsetPages; /* offset in pages to begin remap */ - uint32 numPages; /* number of pages to remap */ + uint32 offsetPages; /* offset in pages to begin remap */ + uint32 numPages; /* number of pages to remap */ /* * Followed by additional data depending on SVGARemapGMR2Flags. * @@ -1547,6 +1434,7 @@ struct { * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry. */ -} SVGAFifoCmdRemapGMR2; +} +SVGAFifoCmdRemapGMR2; #endif diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index 5a72ed908232..5d665ce8cbe4 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c @@ -42,10 +42,6 @@ static uint32_t sys_placement_flags = TTM_PL_FLAG_SYSTEM | static uint32_t gmr_placement_flags = VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; -static uint32_t gmr_ne_placement_flags = VMW_PL_FLAG_GMR | - TTM_PL_FLAG_CACHED | - TTM_PL_FLAG_NO_EVICT; - struct ttm_placement vmw_vram_placement = { .fpfn = 0, .lpfn = 0, @@ -60,11 +56,6 @@ static uint32_t vram_gmr_placement_flags[] = { VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED }; -static uint32_t gmr_vram_placement_flags[] = { - VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED, - TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED -}; - struct ttm_placement vmw_vram_gmr_placement = { .fpfn = 0, .lpfn = 0, @@ -74,20 +65,6 @@ struct ttm_placement vmw_vram_gmr_placement = { .busy_placement = &gmr_placement_flags }; -static uint32_t vram_gmr_ne_placement_flags[] = { - TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT, - VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED | TTM_PL_FLAG_NO_EVICT -}; - -struct ttm_placement vmw_vram_gmr_ne_placement = { - .fpfn = 0, - .lpfn = 0, - .num_placement = 2, - .placement = vram_gmr_ne_placement_flags, - .num_busy_placement = 1, - .busy_placement = &gmr_ne_placement_flags -}; - struct ttm_placement vmw_vram_sys_placement = { .fpfn = 0, .lpfn = 0, @@ -115,30 +92,6 @@ struct ttm_placement vmw_sys_placement = { .busy_placement = &sys_placement_flags }; -static uint32_t evictable_placement_flags[] = { - TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED, - TTM_PL_FLAG_VRAM | TTM_PL_FLAG_CACHED, - VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED -}; - -struct ttm_placement vmw_evictable_placement = { - .fpfn = 0, - .lpfn = 0, - .num_placement = 3, - .placement = evictable_placement_flags, - .num_busy_placement = 1, - .busy_placement = &sys_placement_flags -}; - -struct ttm_placement vmw_srf_placement = { - .fpfn = 0, - .lpfn = 0, - .num_placement = 1, - .num_busy_placement = 2, - .placement = &gmr_placement_flags, - .busy_placement = gmr_vram_placement_flags -}; - struct vmw_ttm_backend { struct ttm_backend backend; struct page **pages; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c deleted file mode 100644 index 3fa884db08ab..000000000000 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ /dev/null @@ -1,322 +0,0 @@ -/************************************************************************** - * - * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "ttm/ttm_placement.h" - -#include "drmP.h" -#include "vmwgfx_drv.h" - - -/** - * vmw_dmabuf_to_placement - Validate a buffer to placement. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @pin: Pin buffer if true. - * @interruptible: Use interruptible wait. - * - * May only be called by the current master since it assumes that the - * master lock is the current master's lock. - * This function takes the master's lock in write mode. - * Flushes and unpins the query bo to avoid failures. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_to_placement(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - struct ttm_placement *placement, - bool interruptible) -{ - struct vmw_master *vmaster = dev_priv->active_master; - struct ttm_buffer_object *bo = &buf->base; - int ret; - - ret = ttm_write_lock(&vmaster->lock, interruptible); - if (unlikely(ret != 0)) - return ret; - - vmw_execbuf_release_pinned_bo(dev_priv, false, 0); - - ret = ttm_bo_reserve(bo, interruptible, false, false, 0); - if (unlikely(ret != 0)) - goto err; - - ret = ttm_bo_validate(bo, placement, interruptible, false, false); - - ttm_bo_unreserve(bo); - -err: - ttm_write_unlock(&vmaster->lock); - return ret; -} - -/** - * vmw_dmabuf_to_vram_or_gmr - Move a buffer to vram or gmr. - * - * May only be called by the current master since it assumes that the - * master lock is the current master's lock. - * This function takes the master's lock in write mode. - * Flushes and unpins the query bo if @pin == true to avoid failures. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @pin: Pin buffer if true. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool interruptible) -{ - struct vmw_master *vmaster = dev_priv->active_master; - struct ttm_buffer_object *bo = &buf->base; - struct ttm_placement *placement; - int ret; - - ret = ttm_write_lock(&vmaster->lock, interruptible); - if (unlikely(ret != 0)) - return ret; - - if (pin) - vmw_execbuf_release_pinned_bo(dev_priv, false, 0); - - ret = ttm_bo_reserve(bo, interruptible, false, false, 0); - if (unlikely(ret != 0)) - goto err; - - /** - * Put BO in VRAM if there is space, otherwise as a GMR. - * If there is no space in VRAM and GMR ids are all used up, - * start evicting GMRs to make room. If the DMA buffer can't be - * used as a GMR, this will return -ENOMEM. - */ - - if (pin) - placement = &vmw_vram_gmr_ne_placement; - else - placement = &vmw_vram_gmr_placement; - - ret = ttm_bo_validate(bo, placement, interruptible, false, false); - if (likely(ret == 0) || ret == -ERESTARTSYS) - goto err_unreserve; - - - /** - * If that failed, try VRAM again, this time evicting - * previous contents. - */ - - if (pin) - placement = &vmw_vram_ne_placement; - else - placement = &vmw_vram_placement; - - ret = ttm_bo_validate(bo, placement, interruptible, false, false); - -err_unreserve: - ttm_bo_unreserve(bo); -err: - ttm_write_unlock(&vmaster->lock); - return ret; -} - -/** - * vmw_dmabuf_to_vram - Move a buffer to vram. - * - * May only be called by the current master since it assumes that the - * master lock is the current master's lock. - * This function takes the master's lock in write mode. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @pin: Pin buffer in vram if true. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_to_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool interruptible) -{ - struct ttm_placement *placement; - - if (pin) - placement = &vmw_vram_ne_placement; - else - placement = &vmw_vram_placement; - - return vmw_dmabuf_to_placement(dev_priv, buf, - placement, - interruptible); -} - -/** - * vmw_dmabuf_to_start_of_vram - Move a buffer to start of vram. - * - * May only be called by the current master since it assumes that the - * master lock is the current master's lock. - * This function takes the master's lock in write mode. - * Flushes and unpins the query bo if @pin == true to avoid failures. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to move. - * @pin: Pin buffer in vram if true. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_to_start_of_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool interruptible) -{ - struct vmw_master *vmaster = dev_priv->active_master; - struct ttm_buffer_object *bo = &buf->base; - struct ttm_placement placement; - int ret = 0; - - if (pin) - placement = vmw_vram_ne_placement; - else - placement = vmw_vram_placement; - placement.lpfn = bo->num_pages; - - ret = ttm_write_lock(&vmaster->lock, interruptible); - if (unlikely(ret != 0)) - return ret; - - if (pin) - vmw_execbuf_release_pinned_bo(dev_priv, false, 0); - - ret = ttm_bo_reserve(bo, interruptible, false, false, 0); - if (unlikely(ret != 0)) - goto err_unlock; - - /* Is this buffer already in vram but not at the start of it? */ - if (bo->mem.mem_type == TTM_PL_VRAM && - bo->mem.start < bo->num_pages && - bo->mem.start > 0) - (void) ttm_bo_validate(bo, &vmw_sys_placement, false, - false, false); - - ret = ttm_bo_validate(bo, &placement, interruptible, false, false); - - /* For some reason we didn't up at the start of vram */ - WARN_ON(ret == 0 && bo->offset != 0); - - ttm_bo_unreserve(bo); -err_unlock: - ttm_write_unlock(&vmaster->lock); - - return ret; -} - - -/** - * vmw_dmabuf_upin - Unpin the buffer given buffer, does not move the buffer. - * - * May only be called by the current master since it assumes that the - * master lock is the current master's lock. - * This function takes the master's lock in write mode. - * - * @dev_priv: Driver private. - * @buf: DMA buffer to unpin. - * @interruptible: Use interruptible wait. - * - * Returns - * -ERESTARTSYS if interrupted by a signal. - */ -int vmw_dmabuf_unpin(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool interruptible) -{ - /* - * We could in theory early out if the buffer is - * unpinned but we need to lock and reserve the buffer - * anyways so we don't gain much by that. - */ - return vmw_dmabuf_to_placement(dev_priv, buf, - &vmw_evictable_placement, - interruptible); -} - - -/** - * vmw_bo_get_guest_ptr - Get the guest ptr representing the current placement - * of a buffer. - * - * @bo: Pointer to a struct ttm_buffer_object. Must be pinned or reserved. - * @ptr: SVGAGuestPtr returning the result. - */ -void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *bo, - SVGAGuestPtr *ptr) -{ - if (bo->mem.mem_type == TTM_PL_VRAM) { - ptr->gmrId = SVGA_GMR_FRAMEBUFFER; - ptr->offset = bo->offset; - } else { - ptr->gmrId = bo->mem.start; - ptr->offset = 0; - } -} - - -/** - * vmw_bo_pin - Pin or unpin a buffer object without moving it. - * - * @bo: The buffer object. Must be reserved, and present either in VRAM - * or GMR memory. - * @pin: Whether to pin or unpin. - * - */ -void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) -{ - uint32_t pl_flags; - struct ttm_placement placement; - uint32_t old_mem_type = bo->mem.mem_type; - int ret; - - BUG_ON(!atomic_read(&bo->reserved)); - BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); - - pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; - if (pin) - pl_flags |= TTM_PL_FLAG_NO_EVICT; - - memset(&placement, 0, sizeof(placement)); - placement.num_placement = 1; - placement.placement = &pl_flags; - - ret = ttm_bo_validate(bo, &placement, false, true, true); - - BUG_ON(ret != 0 || bo->mem.mem_type != old_mem_type); -} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index e07dcf40a3ba..d4829cbf326d 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -94,15 +94,6 @@ #define DRM_IOCTL_VMW_FENCE_UNREF \ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_UNREF, \ struct drm_vmw_fence_arg) -#define DRM_IOCTL_VMW_FENCE_EVENT \ - DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_FENCE_EVENT, \ - struct drm_vmw_fence_event_arg) -#define DRM_IOCTL_VMW_PRESENT \ - DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT, \ - struct drm_vmw_present_arg) -#define DRM_IOCTL_VMW_PRESENT_READBACK \ - DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \ - struct drm_vmw_present_readback_arg) /** * The core DRM version of this macro doesn't account for @@ -153,18 +144,8 @@ static struct drm_ioctl_desc vmw_ioctls[] = { DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl, DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(VMW_FENCE_EVENT, - vmw_fence_event_ioctl, - DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl, DRM_AUTH | DRM_UNLOCKED), - - /* these allow direct access to the framebuffers mark as master only */ - VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl, - DRM_MASTER | DRM_AUTH | DRM_UNLOCKED), - VMW_IOCTL_DEF(VMW_PRESENT_READBACK, - vmw_present_readback_ioctl, - DRM_MASTER | DRM_AUTH | DRM_UNLOCKED), }; static struct pci_device_id vmw_pci_id_list[] = { @@ -219,72 +200,6 @@ static void vmw_print_capabilities(uint32_t capabilities) DRM_INFO(" Screen Object 2.\n"); } - -/** - * vmw_execbuf_prepare_dummy_query - Initialize a query result structure at - * the start of a buffer object. - * - * @dev_priv: The device private structure. - * - * This function will idle the buffer using an uninterruptible wait, then - * map the first page and initialize a pending occlusion query result structure, - * Finally it will unmap the buffer. - * - * TODO: Since we're only mapping a single page, we should optimize the map - * to use kmap_atomic / iomap_atomic. - */ -static void vmw_dummy_query_bo_prepare(struct vmw_private *dev_priv) -{ - struct ttm_bo_kmap_obj map; - volatile SVGA3dQueryResult *result; - bool dummy; - int ret; - struct ttm_bo_device *bdev = &dev_priv->bdev; - struct ttm_buffer_object *bo = dev_priv->dummy_query_bo; - - ttm_bo_reserve(bo, false, false, false, 0); - spin_lock(&bdev->fence_lock); - ret = ttm_bo_wait(bo, false, false, false, TTM_USAGE_READWRITE); - spin_unlock(&bdev->fence_lock); - if (unlikely(ret != 0)) - (void) vmw_fallback_wait(dev_priv, false, true, 0, false, - 10*HZ); - - ret = ttm_bo_kmap(bo, 0, 1, &map); - if (likely(ret == 0)) { - result = ttm_kmap_obj_virtual(&map, &dummy); - result->totalSize = sizeof(*result); - result->state = SVGA3D_QUERYSTATE_PENDING; - result->result32 = 0xff; - ttm_bo_kunmap(&map); - } else - DRM_ERROR("Dummy query buffer map failed.\n"); - ttm_bo_unreserve(bo); -} - - -/** - * vmw_dummy_query_bo_create - create a bo to hold a dummy query result - * - * @dev_priv: A device private structure. - * - * This function creates a small buffer object that holds the query - * result for dummy queries emitted as query barriers. - * No interruptible waits are done within this function. - * - * Returns an error if bo creation fails. - */ -static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) -{ - return ttm_bo_create(&dev_priv->bdev, - PAGE_SIZE, - ttm_bo_type_device, - &vmw_vram_sys_placement, - 0, 0, false, NULL, - &dev_priv->dummy_query_bo); -} - - static int vmw_request_device(struct vmw_private *dev_priv) { int ret; @@ -295,29 +210,12 @@ static int vmw_request_device(struct vmw_private *dev_priv) return ret; } vmw_fence_fifo_up(dev_priv->fman); - ret = vmw_dummy_query_bo_create(dev_priv); - if (unlikely(ret != 0)) - goto out_no_query_bo; - vmw_dummy_query_bo_prepare(dev_priv); return 0; - -out_no_query_bo: - vmw_fence_fifo_down(dev_priv->fman); - vmw_fifo_release(dev_priv, &dev_priv->fifo); - return ret; } static void vmw_release_device(struct vmw_private *dev_priv) { - /* - * Previous destructions should've released - * the pinned bo. - */ - - BUG_ON(dev_priv->pinned_bo != NULL); - - ttm_bo_unref(&dev_priv->dummy_query_bo); vmw_fence_fifo_down(dev_priv->fman); vmw_fifo_release(dev_priv, &dev_priv->fifo); } @@ -408,8 +306,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) init_waitqueue_head(&dev_priv->fifo_queue); dev_priv->fence_queue_waiters = 0; atomic_set(&dev_priv->fifo_queue_waiters, 0); - INIT_LIST_HEAD(&dev_priv->surface_lru); - dev_priv->used_memory_size = 0; dev_priv->io_start = pci_resource_start(dev->pdev, 0); dev_priv->vram_start = pci_resource_start(dev->pdev, 1); @@ -430,10 +326,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES); - dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE); - dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); - dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH); - dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT); if (dev_priv->capabilities & SVGA_CAP_GMR) { dev_priv->max_gmr_descriptors = vmw_read(dev_priv, @@ -446,15 +338,13 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) vmw_read(dev_priv, SVGA_REG_GMRS_MAX_PAGES); dev_priv->memory_size = vmw_read(dev_priv, SVGA_REG_MEMORY_SIZE); - dev_priv->memory_size -= dev_priv->vram_size; - } else { - /* - * An arbitrary limit of 512MiB on surface - * memory. But all HWV8 hardware supports GMR2. - */ - dev_priv->memory_size = 512*1024*1024; } + dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE); + dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); + dev_priv->fb_max_width = vmw_read(dev_priv, SVGA_REG_MAX_WIDTH); + dev_priv->fb_max_height = vmw_read(dev_priv, SVGA_REG_MAX_HEIGHT); + mutex_unlock(&dev_priv->hw_mutex); vmw_print_capabilities(dev_priv->capabilities); @@ -468,8 +358,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv->capabilities & SVGA_CAP_GMR2) { DRM_INFO("Max number of GMR pages is %u\n", (unsigned)dev_priv->max_gmr_pages); - DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n", - (unsigned)dev_priv->memory_size / 1024); + DRM_INFO("Max dedicated hypervisor graphics memory is %u\n", + (unsigned)dev_priv->memory_size); } DRM_INFO("VRAM at 0x%08x size is %u kiB\n", dev_priv->vram_start, dev_priv->vram_size / 1024); @@ -561,30 +451,22 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->fman = vmw_fence_manager_init(dev_priv); if (unlikely(dev_priv->fman == NULL)) goto out_no_fman; - - /* Need to start the fifo to check if we can do screen objects */ - ret = vmw_3d_resource_inc(dev_priv, true); - if (unlikely(ret != 0)) - goto out_no_fifo; - vmw_kms_save_vga(dev_priv); - - /* Start kms and overlay systems, needs fifo. */ ret = vmw_kms_init(dev_priv); if (unlikely(ret != 0)) goto out_no_kms; vmw_overlay_init(dev_priv); - - /* 3D Depends on Screen Objects being used. */ - DRM_INFO("Detected %sdevice 3D availability.\n", - vmw_fifo_have_3d(dev_priv) ? - "" : "no "); - - /* We might be done with the fifo now */ if (dev_priv->enable_fb) { + ret = vmw_3d_resource_inc(dev_priv, false); + if (unlikely(ret != 0)) + goto out_no_fifo; + vmw_kms_save_vga(dev_priv); vmw_fb_init(dev_priv); + DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? + "Detected device 3D availability.\n" : + "Detected no device 3D availability.\n"); } else { - vmw_kms_restore_vga(dev_priv); - vmw_3d_resource_dec(dev_priv, true); + DRM_INFO("Delayed 3D detection since we're not " + "running the device in SVGA mode yet.\n"); } if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { @@ -601,17 +483,15 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) return 0; out_no_irq: - if (dev_priv->enable_fb) - vmw_fb_close(dev_priv); - vmw_overlay_close(dev_priv); - vmw_kms_close(dev_priv); -out_no_kms: - /* We still have a 3D resource reference held */ if (dev_priv->enable_fb) { + vmw_fb_close(dev_priv); vmw_kms_restore_vga(dev_priv); vmw_3d_resource_dec(dev_priv, false); } out_no_fifo: + vmw_overlay_close(dev_priv); + vmw_kms_close(dev_priv); +out_no_kms: vmw_fence_manager_takedown(dev_priv->fman); out_no_fman: if (dev_priv->stealth) @@ -891,7 +771,7 @@ static void vmw_master_drop(struct drm_device *dev, vmw_fp->locked_master = drm_master_get(file_priv->master); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); - vmw_execbuf_release_pinned_bo(dev_priv, false, 0); + vmw_kms_idle_workqueues(vmaster); if (unlikely((ret != 0))) { DRM_ERROR("Unable to lock TTM at VT switch.\n"); @@ -943,7 +823,6 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, * This empties VRAM and unbinds all GMR bindings. * Buffer contents is moved to swappable memory. */ - vmw_execbuf_release_pinned_bo(dev_priv, false, 0); ttm_bo_swapout_all(&dev_priv->bdev); break; @@ -1085,8 +964,7 @@ static struct drm_driver driver = { .release = drm_release, .unlocked_ioctl = vmw_unlocked_ioctl, .mmap = vmw_mmap, - .poll = vmw_fops_poll, - .read = vmw_fops_read, + .poll = drm_poll, .fasync = drm_fasync, #if defined(CONFIG_COMPAT) .compat_ioctl = drm_compat_ioctl, diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 0e9b2cefaa9d..564a81582111 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -40,9 +40,9 @@ #include "ttm/ttm_module.h" #include "vmwgfx_fence.h" -#define VMWGFX_DRIVER_DATE "20111008" +#define VMWGFX_DRIVER_DATE "20110901" #define VMWGFX_DRIVER_MAJOR 2 -#define VMWGFX_DRIVER_MINOR 2 +#define VMWGFX_DRIVER_MINOR 0 #define VMWGFX_DRIVER_PATCHLEVEL 0 #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) @@ -79,11 +79,9 @@ struct vmw_resource { int id; enum ttm_object_type res_type; bool avail; - void (*remove_from_lists) (struct vmw_resource *res); void (*hw_destroy) (struct vmw_resource *res); void (*res_free) (struct vmw_resource *res); - struct list_head validate_head; - struct list_head query_head; /* Protected by the cmdbuf mutex */ + bool on_validate_list; /* TODO is a generic snooper needed? */ #if 0 void (*snoop)(struct vmw_resource *res, @@ -99,12 +97,8 @@ struct vmw_cursor_snooper { uint32_t *image; }; -struct vmw_framebuffer; -struct vmw_surface_offset; - struct vmw_surface { struct vmw_resource res; - struct list_head lru_head; /* Protected by the resource lock */ uint32_t flags; uint32_t format; uint32_t mip_levels[DRM_VMW_MAX_SURFACE_FACES]; @@ -115,9 +109,6 @@ struct vmw_surface { /* TODO so far just a extra pointer */ struct vmw_cursor_snooper snooper; - struct ttm_buffer_object *backup; - struct vmw_surface_offset *offsets; - uint32_t backup_size; }; struct vmw_marker_queue { @@ -148,8 +139,6 @@ struct vmw_sw_context{ struct ida bo_list; uint32_t last_cid; bool cid_valid; - bool kernel; /**< is the called made from the kernel */ - struct vmw_resource *cur_ctx; uint32_t last_sid; uint32_t sid_translation; bool sid_valid; @@ -161,12 +150,8 @@ struct vmw_sw_context{ uint32_t cur_val_buf; uint32_t *cmd_bounce; uint32_t cmd_bounce_size; - struct list_head resource_list; - uint32_t fence_flags; - struct list_head query_list; - struct ttm_buffer_object *cur_query_bo; - uint32_t cur_query_cid; - bool query_cid_valid; + struct vmw_resource *resources[VMWGFX_MAX_VALIDATIONS]; + uint32_t num_ref_resources; }; struct vmw_legacy_display; @@ -231,7 +216,6 @@ struct vmw_private { void *fb_info; struct vmw_legacy_display *ldu_priv; - struct vmw_screen_object_display *sou_priv; struct vmw_overlay *overlay_priv; /* @@ -264,12 +248,10 @@ struct vmw_private { wait_queue_head_t fence_queue; wait_queue_head_t fifo_queue; int fence_queue_waiters; /* Protected by hw_mutex */ - int goal_queue_waiters; /* Protected by hw_mutex */ atomic_t fifo_queue_waiters; uint32_t last_read_seqno; spinlock_t irq_lock; struct vmw_fence_manager *fman; - uint32_t irq_mask; /* * Device state @@ -308,26 +290,6 @@ struct vmw_private { struct mutex release_mutex; uint32_t num_3d_resources; - - /* - * Query processing. These members - * are protected by the cmdbuf mutex. - */ - - struct ttm_buffer_object *dummy_query_bo; - struct ttm_buffer_object *pinned_bo; - uint32_t query_cid; - bool dummy_query_bo_pinned; - - /* - * Surface swapping. The "surface_lru" list is protected by the - * resource lock in order to be able to destroy a surface and take - * it off the lru atomically. "used_memory_size" is currently - * protected by the cmdbuf mutex for simplicity. - */ - - struct list_head surface_lru; - uint32_t used_memory_size; }; static inline struct vmw_private *vmw_priv(struct drm_device *dev) @@ -407,8 +369,6 @@ extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, extern int vmw_surface_check(struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t handle, int *id); -extern int vmw_surface_validate(struct vmw_private *dev_priv, - struct vmw_surface *srf); extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo); extern int vmw_dmabuf_init(struct vmw_private *dev_priv, struct vmw_dma_buffer *vmw_bo, @@ -424,6 +384,10 @@ extern uint32_t vmw_dmabuf_validate_node(struct ttm_buffer_object *bo, extern void vmw_dmabuf_validate_clear(struct ttm_buffer_object *bo); extern int vmw_user_dmabuf_lookup(struct ttm_object_file *tfile, uint32_t id, struct vmw_dma_buffer **out); +extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, + struct vmw_dma_buffer *bo); +extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv, + struct vmw_dma_buffer *bo); extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, @@ -432,30 +396,7 @@ extern int vmw_user_stream_lookup(struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t *inout_id, struct vmw_resource **out); -extern void vmw_resource_unreserve(struct list_head *list); -/** - * DMA buffer helper routines - vmwgfx_dmabuf.c - */ -extern int vmw_dmabuf_to_placement(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - struct ttm_placement *placement, - bool interruptible); -extern int vmw_dmabuf_to_vram(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool interruptible); -extern int vmw_dmabuf_to_vram_or_gmr(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool interruptible); -extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - bool pin, bool interruptible); -extern int vmw_dmabuf_unpin(struct vmw_private *vmw_priv, - struct vmw_dma_buffer *bo, - bool interruptible); -extern void vmw_bo_get_guest_ptr(const struct ttm_buffer_object *buf, - SVGAGuestPtr *ptr); -extern void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin); /** * Misc Ioctl functionality - vmwgfx_ioctl.c @@ -465,14 +406,6 @@ extern int vmw_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int vmw_present_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern unsigned int vmw_fops_poll(struct file *filp, - struct poll_table_struct *wait); -extern ssize_t vmw_fops_read(struct file *filp, char __user *buffer, - size_t count, loff_t *offset); /** * Fifo utilities - vmwgfx_fifo.c @@ -489,8 +422,6 @@ extern int vmw_fifo_send_fence(struct vmw_private *dev_priv, extern void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason); extern bool vmw_fifo_have_3d(struct vmw_private *dev_priv); extern bool vmw_fifo_have_pitchlock(struct vmw_private *dev_priv); -extern int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv, - uint32_t cid); /** * TTM glue - vmwgfx_ttm_glue.c @@ -508,10 +439,7 @@ extern struct ttm_placement vmw_vram_placement; extern struct ttm_placement vmw_vram_ne_placement; extern struct ttm_placement vmw_vram_sys_placement; extern struct ttm_placement vmw_vram_gmr_placement; -extern struct ttm_placement vmw_vram_gmr_ne_placement; extern struct ttm_placement vmw_sys_placement; -extern struct ttm_placement vmw_evictable_placement; -extern struct ttm_placement vmw_srf_placement; extern struct ttm_bo_driver vmw_bo_driver; extern int vmw_dma_quiescent(struct drm_device *dev); @@ -521,30 +449,6 @@ extern int vmw_dma_quiescent(struct drm_device *dev); extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int vmw_execbuf_process(struct drm_file *file_priv, - struct vmw_private *dev_priv, - void __user *user_commands, - void *kernel_commands, - uint32_t command_size, - uint64_t throttle_us, - struct drm_vmw_fence_rep __user - *user_fence_rep); - -extern void -vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, - bool only_on_cid_match, uint32_t cid); - -extern int vmw_execbuf_fence_commands(struct drm_file *file_priv, - struct vmw_private *dev_priv, - struct vmw_fence_obj **p_fence, - uint32_t *p_handle); -extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, - struct vmw_fpriv *vmw_fp, - int ret, - struct drm_vmw_fence_rep __user - *user_fence_rep, - struct vmw_fence_obj *fence, - uint32_t fence_handle); /** * IRQs and wating - vmwgfx_irq.c @@ -569,8 +473,6 @@ extern void vmw_update_seqno(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo_state); extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv); extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv); -extern void vmw_goal_waiter_add(struct vmw_private *dev_priv); -extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv); /** * Rudimentary fence-like objects currently used only for throttling - @@ -618,19 +520,6 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, uint32_t pitch, uint32_t height); u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc); -int vmw_kms_present(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct vmw_surface *surface, - uint32_t sid, int32_t destX, int32_t destY, - struct drm_vmw_rect *clips, - uint32_t num_clips); -int vmw_kms_readback(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct drm_vmw_fence_rep __user *user_fence_rep, - struct drm_vmw_rect *clips, - uint32_t num_clips); /** * Overlay control - vmwgfx_overlay.c diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index d4a1d8b06336..fa26e647f488 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -44,64 +44,28 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv, return 0; } -static void vmw_resource_to_validate_list(struct vmw_sw_context *sw_context, - struct vmw_resource **p_res) -{ - struct vmw_resource *res = *p_res; - - if (list_empty(&res->validate_head)) { - list_add_tail(&res->validate_head, &sw_context->resource_list); - *p_res = NULL; - } else - vmw_resource_unreference(p_res); -} -/** - * vmw_bo_to_validate_list - add a bo to a validate list - * - * @sw_context: The software context used for this command submission batch. - * @bo: The buffer object to add. - * @fence_flags: Fence flags to be or'ed with any other fence flags for - * this buffer on this submission batch. - * @p_val_node: If non-NULL Will be updated with the validate node number - * on return. - * - * Returns -EINVAL if the limit of number of buffer objects per command - * submission is reached. - */ -static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, - struct ttm_buffer_object *bo, - uint32_t fence_flags, - uint32_t *p_val_node) +static int vmw_resource_to_validate_list(struct vmw_sw_context *sw_context, + struct vmw_resource **p_res) { - uint32_t val_node; - struct ttm_validate_buffer *val_buf; - - val_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf); - - if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) { - DRM_ERROR("Max number of DMA buffers per submission" - " exceeded.\n"); - return -EINVAL; - } + int ret = 0; + struct vmw_resource *res = *p_res; - val_buf = &sw_context->val_bufs[val_node]; - if (unlikely(val_node == sw_context->cur_val_buf)) { - val_buf->new_sync_obj_arg = NULL; - val_buf->bo = ttm_bo_reference(bo); - val_buf->usage = TTM_USAGE_READWRITE; - list_add_tail(&val_buf->head, &sw_context->validate_nodes); - ++sw_context->cur_val_buf; + if (!res->on_validate_list) { + if (sw_context->num_ref_resources >= VMWGFX_MAX_VALIDATIONS) { + DRM_ERROR("Too many resources referenced in " + "command stream.\n"); + ret = -ENOMEM; + goto out; + } + sw_context->resources[sw_context->num_ref_resources++] = res; + res->on_validate_list = true; + return 0; } - val_buf->new_sync_obj_arg = (void *) - ((unsigned long) val_buf->new_sync_obj_arg | fence_flags); - sw_context->fence_flags |= fence_flags; - - if (p_val_node) - *p_val_node = val_node; - - return 0; +out: + vmw_resource_unreference(p_res); + return ret; } static int vmw_cmd_cid_check(struct vmw_private *dev_priv, @@ -130,10 +94,7 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, sw_context->last_cid = cmd->cid; sw_context->cid_valid = true; - sw_context->cur_ctx = ctx; - vmw_resource_to_validate_list(sw_context, &ctx); - - return 0; + return vmw_resource_to_validate_list(sw_context, &ctx); } static int vmw_cmd_sid_check(struct vmw_private *dev_priv, @@ -153,8 +114,7 @@ static int vmw_cmd_sid_check(struct vmw_private *dev_priv, return 0; } - ret = vmw_user_surface_lookup_handle(dev_priv, - sw_context->tfile, + ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile, *sid, &srf); if (unlikely(ret != 0)) { DRM_ERROR("Could ot find or use surface 0x%08x " @@ -164,23 +124,13 @@ static int vmw_cmd_sid_check(struct vmw_private *dev_priv, return ret; } - ret = vmw_surface_validate(dev_priv, srf); - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Could not validate surface.\n"); - vmw_surface_unreference(&srf); - return ret; - } - sw_context->last_sid = *sid; sw_context->sid_valid = true; sw_context->sid_translation = srf->res.id; *sid = sw_context->sid_translation; res = &srf->res; - vmw_resource_to_validate_list(sw_context, &res); - - return 0; + return vmw_resource_to_validate_list(sw_context, &res); } @@ -247,12 +197,6 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, } *cmd; cmd = container_of(header, struct vmw_sid_cmd, header); - - if (unlikely(!sw_context->kernel)) { - DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id); - return -EPERM; - } - return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid); } @@ -265,179 +209,10 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, SVGA3dCmdPresent body; } *cmd; - cmd = container_of(header, struct vmw_sid_cmd, header); - - if (unlikely(!sw_context->kernel)) { - DRM_ERROR("Kernel only SVGA3d command: %u.\n", cmd->header.id); - return -EPERM; - } - return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid); } -/** - * vmw_query_bo_switch_prepare - Prepare to switch pinned buffer for queries. - * - * @dev_priv: The device private structure. - * @cid: The hardware context for the next query. - * @new_query_bo: The new buffer holding query results. - * @sw_context: The software context used for this command submission. - * - * This function checks whether @new_query_bo is suitable for holding - * query results, and if another buffer currently is pinned for query - * results. If so, the function prepares the state of @sw_context for - * switching pinned buffers after successful submission of the current - * command batch. It also checks whether we're using a new query context. - * In that case, it makes sure we emit a query barrier for the old - * context before the current query buffer is fenced. - */ -static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, - uint32_t cid, - struct ttm_buffer_object *new_query_bo, - struct vmw_sw_context *sw_context) -{ - int ret; - bool add_cid = false; - uint32_t cid_to_add; - - if (unlikely(new_query_bo != sw_context->cur_query_bo)) { - - if (unlikely(new_query_bo->num_pages > 4)) { - DRM_ERROR("Query buffer too large.\n"); - return -EINVAL; - } - - if (unlikely(sw_context->cur_query_bo != NULL)) { - BUG_ON(!sw_context->query_cid_valid); - add_cid = true; - cid_to_add = sw_context->cur_query_cid; - ret = vmw_bo_to_validate_list(sw_context, - sw_context->cur_query_bo, - DRM_VMW_FENCE_FLAG_EXEC, - NULL); - if (unlikely(ret != 0)) - return ret; - } - sw_context->cur_query_bo = new_query_bo; - - ret = vmw_bo_to_validate_list(sw_context, - dev_priv->dummy_query_bo, - DRM_VMW_FENCE_FLAG_EXEC, - NULL); - if (unlikely(ret != 0)) - return ret; - - } - - if (unlikely(cid != sw_context->cur_query_cid && - sw_context->query_cid_valid)) { - add_cid = true; - cid_to_add = sw_context->cur_query_cid; - } - - sw_context->cur_query_cid = cid; - sw_context->query_cid_valid = true; - - if (add_cid) { - struct vmw_resource *ctx = sw_context->cur_ctx; - - if (list_empty(&ctx->query_head)) - list_add_tail(&ctx->query_head, - &sw_context->query_list); - ret = vmw_bo_to_validate_list(sw_context, - dev_priv->dummy_query_bo, - DRM_VMW_FENCE_FLAG_EXEC, - NULL); - if (unlikely(ret != 0)) - return ret; - } - return 0; -} - - -/** - * vmw_query_bo_switch_commit - Finalize switching pinned query buffer - * - * @dev_priv: The device private structure. - * @sw_context: The software context used for this command submission batch. - * - * This function will check if we're switching query buffers, and will then, - * if no other query waits are issued this command submission batch, - * issue a dummy occlusion query wait used as a query barrier. When the fence - * object following that query wait has signaled, we are sure that all - * preseding queries have finished, and the old query buffer can be unpinned. - * However, since both the new query buffer and the old one are fenced with - * that fence, we can do an asynchronus unpin now, and be sure that the - * old query buffer won't be moved until the fence has signaled. - * - * As mentioned above, both the new - and old query buffers need to be fenced - * using a sequence emitted *after* calling this function. - */ -static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context) -{ - - struct vmw_resource *ctx, *next_ctx; - int ret; - - /* - * The validate list should still hold references to all - * contexts here. - */ - - list_for_each_entry_safe(ctx, next_ctx, &sw_context->query_list, - query_head) { - list_del_init(&ctx->query_head); - - BUG_ON(list_empty(&ctx->validate_head)); - - ret = vmw_fifo_emit_dummy_query(dev_priv, ctx->id); - - if (unlikely(ret != 0)) - DRM_ERROR("Out of fifo space for dummy query.\n"); - } - - if (dev_priv->pinned_bo != sw_context->cur_query_bo) { - if (dev_priv->pinned_bo) { - vmw_bo_pin(dev_priv->pinned_bo, false); - ttm_bo_unref(&dev_priv->pinned_bo); - } - - vmw_bo_pin(sw_context->cur_query_bo, true); - - /* - * We pin also the dummy_query_bo buffer so that we - * don't need to validate it when emitting - * dummy queries in context destroy paths. - */ - - vmw_bo_pin(dev_priv->dummy_query_bo, true); - dev_priv->dummy_query_bo_pinned = true; - - dev_priv->query_cid = sw_context->cur_query_cid; - dev_priv->pinned_bo = - ttm_bo_reference(sw_context->cur_query_bo); - } -} - -/** - * vmw_query_switch_backoff - clear query barrier list - * @sw_context: The sw context used for this submission batch. - * - * This function is used as part of an error path, where a previously - * set up list of query barriers needs to be cleared. - * - */ -static void vmw_query_switch_backoff(struct vmw_sw_context *sw_context) -{ - struct list_head *list, *next; - - list_for_each_safe(list, next, &sw_context->query_list) { - list_del_init(list); - } -} - static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGAGuestPtr *ptr, @@ -447,6 +222,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, struct ttm_buffer_object *bo; uint32_t handle = ptr->gmrId; struct vmw_relocation *reloc; + uint32_t cur_validate_node; + struct ttm_validate_buffer *val_buf; int ret; ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); @@ -466,11 +243,23 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, reloc = &sw_context->relocs[sw_context->cur_reloc++]; reloc->location = ptr; - ret = vmw_bo_to_validate_list(sw_context, bo, DRM_VMW_FENCE_FLAG_EXEC, - &reloc->index); - if (unlikely(ret != 0)) + cur_validate_node = vmw_dmabuf_validate_node(bo, sw_context->cur_val_buf); + if (unlikely(cur_validate_node >= VMWGFX_MAX_VALIDATIONS)) { + DRM_ERROR("Max number of DMA buffers per submission" + " exceeded.\n"); + ret = -EINVAL; goto out_no_reloc; + } + reloc->index = cur_validate_node; + if (unlikely(cur_validate_node == sw_context->cur_val_buf)) { + val_buf = &sw_context->val_bufs[cur_validate_node]; + val_buf->bo = ttm_bo_reference(bo); + val_buf->usage = TTM_USAGE_READWRITE; + val_buf->new_sync_obj_arg = (void *) DRM_VMW_FENCE_FLAG_EXEC; + list_add_tail(&val_buf->head, &sw_context->validate_nodes); + ++sw_context->cur_val_buf; + } *vmw_bo_p = vmw_bo; return 0; @@ -502,11 +291,8 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; - ret = vmw_query_bo_switch_prepare(dev_priv, cmd->q.cid, - &vmw_bo->base, sw_context); - vmw_dmabuf_unreference(&vmw_bo); - return ret; + return 0; } static int vmw_cmd_wait_query(struct vmw_private *dev_priv, @@ -519,7 +305,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, SVGA3dCmdWaitForQuery q; } *cmd; int ret; - struct vmw_resource *ctx; cmd = container_of(header, struct vmw_query_cmd, header); ret = vmw_cmd_cid_check(dev_priv, sw_context, header); @@ -533,16 +318,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv, return ret; vmw_dmabuf_unreference(&vmw_bo); - - /* - * This wait will act as a barrier for previous waits for this - * context. - */ - - ctx = sw_context->cur_ctx; - if (!list_empty(&ctx->query_head)) - list_del_init(&ctx->query_head); - return 0; } @@ -575,13 +350,6 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, goto out_no_reloc; } - ret = vmw_surface_validate(dev_priv, srf); - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Culd not validate surface.\n"); - goto out_no_validate; - } - /* * Patch command stream with device SID. */ @@ -591,12 +359,8 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, vmw_dmabuf_unreference(&vmw_bo); res = &srf->res; - vmw_resource_to_validate_list(sw_context, &res); - - return 0; + return vmw_resource_to_validate_list(sw_context, &res); -out_no_validate: - vmw_surface_unreference(&srf); out_no_reloc: vmw_dmabuf_unreference(&vmw_bo); return ret; @@ -686,71 +450,6 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, return 0; } -static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - void *buf) -{ - struct vmw_dma_buffer *vmw_bo; - int ret; - - struct { - uint32_t header; - SVGAFifoCmdDefineGMRFB body; - } *cmd = buf; - - ret = vmw_translate_guest_ptr(dev_priv, sw_context, - &cmd->body.ptr, - &vmw_bo); - if (unlikely(ret != 0)) - return ret; - - vmw_dmabuf_unreference(&vmw_bo); - - return ret; -} - -static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context, - void *buf, uint32_t *size) -{ - uint32_t size_remaining = *size; - uint32_t cmd_id; - - cmd_id = le32_to_cpu(((uint32_t *)buf)[0]); - switch (cmd_id) { - case SVGA_CMD_UPDATE: - *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdUpdate); - break; - case SVGA_CMD_DEFINE_GMRFB: - *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMRFB); - break; - case SVGA_CMD_BLIT_GMRFB_TO_SCREEN: - *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); - break; - case SVGA_CMD_BLIT_SCREEN_TO_GMRFB: - *size = sizeof(uint32_t) + sizeof(SVGAFifoCmdBlitGMRFBToScreen); - break; - default: - DRM_ERROR("Unsupported SVGA command: %u.\n", cmd_id); - return -EINVAL; - } - - if (*size > size_remaining) { - DRM_ERROR("Invalid SVGA command (size mismatch):" - " %u.\n", cmd_id); - return -EINVAL; - } - - if (unlikely(!sw_context->kernel)) { - DRM_ERROR("Kernel only SVGA command: %u.\n", cmd_id); - return -EPERM; - } - - if (cmd_id == SVGA_CMD_DEFINE_GMRFB) - return vmw_cmd_check_define_gmrfb(dev_priv, sw_context, buf); - - return 0; -} typedef int (*vmw_cmd_func) (struct vmw_private *, struct vmw_sw_context *, @@ -803,11 +502,11 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; int ret; - cmd_id = le32_to_cpu(((uint32_t *)buf)[0]); - /* Handle any none 3D commands */ - if (unlikely(cmd_id < SVGA_CMD_MAX)) - return vmw_cmd_check_not_3d(dev_priv, sw_context, buf, size); - + cmd_id = ((uint32_t *)buf)[0]; + if (cmd_id == SVGA_CMD_UPDATE) { + *size = 5 << 2; + return 0; + } cmd_id = le32_to_cpu(header->id); *size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader); @@ -832,9 +531,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, static int vmw_cmd_check_all(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, - void *buf, uint32_t size) { + void *buf = sw_context->cmd_bounce; int32_t cur_size = size; int ret; @@ -883,7 +582,7 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) static void vmw_clear_validations(struct vmw_sw_context *sw_context) { struct ttm_validate_buffer *entry, *next; - struct vmw_resource *res, *res_next; + uint32_t i = sw_context->num_ref_resources; /* * Drop references to DMA buffers held during command submission. @@ -900,11 +599,9 @@ static void vmw_clear_validations(struct vmw_sw_context *sw_context) /* * Drop references to resources held during command submission. */ - vmw_resource_unreserve(&sw_context->resource_list); - list_for_each_entry_safe(res, res_next, &sw_context->resource_list, - validate_head) { - list_del_init(&res->validate_head); - vmw_resource_unreference(&res); + while (i-- > 0) { + sw_context->resources[i]->on_validate_list = false; + vmw_resource_unreference(&sw_context->resources[i]); } } @@ -913,16 +610,6 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, { int ret; - - /* - * Don't validate pinned buffers. - */ - - if (bo == dev_priv->pinned_bo || - (bo == dev_priv->dummy_query_bo && - dev_priv->dummy_query_bo_pinned)) - return 0; - /** * Put BO in VRAM if there is space, otherwise as a GMR. * If there is no space in VRAM and GMR ids are all used up, @@ -994,9 +681,6 @@ static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context, * Creates a fence object and submits a command stream marker. * If this fails for some reason, We sync the fifo and return NULL. * It is then safe to fence buffers with a NULL pointer. - * - * If @p_handle is not NULL @file_priv must also not be NULL. Creates - * a userspace handle if @p_handle is not NULL, otherwise not. */ int vmw_execbuf_fence_commands(struct drm_file *file_priv, @@ -1008,8 +692,6 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, int ret; bool synced = false; - /* p_handle implies file_priv. */ - BUG_ON(p_handle != NULL && file_priv == NULL); ret = vmw_fifo_send_fence(dev_priv, &sequence); if (unlikely(ret != 0)) { @@ -1037,125 +719,69 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv, return 0; } -/** - * vmw_execbuf_copy_fence_user - copy fence object information to - * user-space. - * - * @dev_priv: Pointer to a vmw_private struct. - * @vmw_fp: Pointer to the struct vmw_fpriv representing the calling file. - * @ret: Return value from fence object creation. - * @user_fence_rep: User space address of a struct drm_vmw_fence_rep to - * which the information should be copied. - * @fence: Pointer to the fenc object. - * @fence_handle: User-space fence handle. - * - * This function copies fence information to user-space. If copying fails, - * The user-space struct drm_vmw_fence_rep::error member is hopefully - * left untouched, and if it's preloaded with an -EFAULT by user-space, - * the error will hopefully be detected. - * Also if copying fails, user-space will be unable to signal the fence - * object so we wait for it immediately, and then unreference the - * user-space reference. - */ -void -vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, - struct vmw_fpriv *vmw_fp, - int ret, - struct drm_vmw_fence_rep __user *user_fence_rep, - struct vmw_fence_obj *fence, - uint32_t fence_handle) +int vmw_execbuf_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { + struct vmw_private *dev_priv = vmw_priv(dev); + struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data; struct drm_vmw_fence_rep fence_rep; - - if (user_fence_rep == NULL) - return; - - fence_rep.error = ret; - if (ret == 0) { - BUG_ON(fence == NULL); - - fence_rep.handle = fence_handle; - fence_rep.seqno = fence->seqno; - vmw_update_seqno(dev_priv, &dev_priv->fifo); - fence_rep.passed_seqno = dev_priv->last_read_seqno; - } + struct drm_vmw_fence_rep __user *user_fence_rep; + int ret; + void *user_cmd; + void *cmd; + struct vmw_sw_context *sw_context = &dev_priv->ctx; + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct vmw_fence_obj *fence; + uint32_t handle; /* - * copy_to_user errors will be detected by user space not - * seeing fence_rep::error filled in. Typically - * user-space would have pre-set that member to -EFAULT. + * This will allow us to extend the ioctl argument while + * maintaining backwards compatibility: + * We take different code paths depending on the value of + * arg->version. */ - ret = copy_to_user(user_fence_rep, &fence_rep, - sizeof(fence_rep)); - /* - * User-space lost the fence object. We need to sync - * and unreference the handle. - */ - if (unlikely(ret != 0) && (fence_rep.error == 0)) { - ttm_ref_object_base_unref(vmw_fp->tfile, - fence_handle, TTM_REF_USAGE); - DRM_ERROR("Fence copy error. Syncing.\n"); - (void) vmw_fence_obj_wait(fence, fence->signal_mask, - false, false, - VMW_FENCE_WAIT_TIMEOUT); + if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) { + DRM_ERROR("Incorrect execbuf version.\n"); + DRM_ERROR("You're running outdated experimental " + "vmwgfx user-space drivers."); + return -EINVAL; } -} - -int vmw_execbuf_process(struct drm_file *file_priv, - struct vmw_private *dev_priv, - void __user *user_commands, - void *kernel_commands, - uint32_t command_size, - uint64_t throttle_us, - struct drm_vmw_fence_rep __user *user_fence_rep) -{ - struct vmw_sw_context *sw_context = &dev_priv->ctx; - struct vmw_fence_obj *fence; - uint32_t handle; - void *cmd; - int ret; - ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); + ret = ttm_read_lock(&vmaster->lock, true); if (unlikely(ret != 0)) - return -ERESTARTSYS; - - if (kernel_commands == NULL) { - sw_context->kernel = false; + return ret; - ret = vmw_resize_cmd_bounce(sw_context, command_size); - if (unlikely(ret != 0)) - goto out_unlock; + ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); + if (unlikely(ret != 0)) { + ret = -ERESTARTSYS; + goto out_no_cmd_mutex; + } + ret = vmw_resize_cmd_bounce(sw_context, arg->command_size); + if (unlikely(ret != 0)) + goto out_unlock; - ret = copy_from_user(sw_context->cmd_bounce, - user_commands, command_size); + user_cmd = (void __user *)(unsigned long)arg->commands; + ret = copy_from_user(sw_context->cmd_bounce, + user_cmd, arg->command_size); - if (unlikely(ret != 0)) { - ret = -EFAULT; - DRM_ERROR("Failed copying commands.\n"); - goto out_unlock; - } - kernel_commands = sw_context->cmd_bounce; - } else - sw_context->kernel = true; + if (unlikely(ret != 0)) { + ret = -EFAULT; + DRM_ERROR("Failed copying commands.\n"); + goto out_unlock; + } sw_context->tfile = vmw_fpriv(file_priv)->tfile; sw_context->cid_valid = false; sw_context->sid_valid = false; sw_context->cur_reloc = 0; sw_context->cur_val_buf = 0; - sw_context->fence_flags = 0; - INIT_LIST_HEAD(&sw_context->query_list); - INIT_LIST_HEAD(&sw_context->resource_list); - sw_context->cur_query_bo = dev_priv->pinned_bo; - sw_context->cur_query_cid = dev_priv->query_cid; - sw_context->query_cid_valid = (dev_priv->pinned_bo != NULL); + sw_context->num_ref_resources = 0; INIT_LIST_HEAD(&sw_context->validate_nodes); - ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, - command_size); + ret = vmw_cmd_check_all(dev_priv, sw_context, arg->command_size); if (unlikely(ret != 0)) goto out_err; @@ -1169,25 +795,26 @@ int vmw_execbuf_process(struct drm_file *file_priv, vmw_apply_relocations(sw_context); - if (throttle_us) { + if (arg->throttle_us) { ret = vmw_wait_lag(dev_priv, &dev_priv->fifo.marker_queue, - throttle_us); + arg->throttle_us); if (unlikely(ret != 0)) goto out_throttle; } - cmd = vmw_fifo_reserve(dev_priv, command_size); + cmd = vmw_fifo_reserve(dev_priv, arg->command_size); if (unlikely(cmd == NULL)) { DRM_ERROR("Failed reserving fifo space for commands.\n"); ret = -ENOMEM; - goto out_throttle; + goto out_err; } - memcpy(cmd, kernel_commands, command_size); - vmw_fifo_commit(dev_priv, command_size); + memcpy(cmd, sw_context->cmd_bounce, arg->command_size); + vmw_fifo_commit(dev_priv, arg->command_size); - vmw_query_bo_switch_commit(dev_priv, sw_context); + user_fence_rep = (struct drm_vmw_fence_rep __user *) + (unsigned long)arg->fence_rep; ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence, (user_fence_rep) ? &handle : NULL); @@ -1204,171 +831,54 @@ int vmw_execbuf_process(struct drm_file *file_priv, (void *) fence); vmw_clear_validations(sw_context); - vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret, - user_fence_rep, fence, handle); + mutex_unlock(&dev_priv->cmdbuf_mutex); + + if (user_fence_rep) { + fence_rep.error = ret; + fence_rep.handle = handle; + fence_rep.seqno = fence->seqno; + vmw_update_seqno(dev_priv, &dev_priv->fifo); + fence_rep.passed_seqno = dev_priv->last_read_seqno; + + /* + * copy_to_user errors will be detected by user space not + * seeing fence_rep::error filled in. Typically + * user-space would have pre-set that member to -EFAULT. + */ + ret = copy_to_user(user_fence_rep, &fence_rep, + sizeof(fence_rep)); + + /* + * User-space lost the fence object. We need to sync + * and unreference the handle. + */ + if (unlikely(ret != 0) && (fence_rep.error == 0)) { + BUG_ON(fence == NULL); + + ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); + DRM_ERROR("Fence copy error. Syncing.\n"); + (void) vmw_fence_obj_wait(fence, + fence->signal_mask, + false, false, + VMW_FENCE_WAIT_TIMEOUT); + } + } if (likely(fence != NULL)) vmw_fence_obj_unreference(&fence); - mutex_unlock(&dev_priv->cmdbuf_mutex); + vmw_kms_cursor_post_execbuf(dev_priv); + ttm_read_unlock(&vmaster->lock); return 0; - out_err: vmw_free_relocations(sw_context); out_throttle: - vmw_query_switch_backoff(sw_context); ttm_eu_backoff_reservation(&sw_context->validate_nodes); vmw_clear_validations(sw_context); out_unlock: mutex_unlock(&dev_priv->cmdbuf_mutex); - return ret; -} - -/** - * vmw_execbuf_unpin_panic - Idle the fifo and unpin the query buffer. - * - * @dev_priv: The device private structure. - * - * This function is called to idle the fifo and unpin the query buffer - * if the normal way to do this hits an error, which should typically be - * extremely rare. - */ -static void vmw_execbuf_unpin_panic(struct vmw_private *dev_priv) -{ - DRM_ERROR("Can't unpin query buffer. Trying to recover.\n"); - - (void) vmw_fallback_wait(dev_priv, false, true, 0, false, 10*HZ); - vmw_bo_pin(dev_priv->pinned_bo, false); - vmw_bo_pin(dev_priv->dummy_query_bo, false); - dev_priv->dummy_query_bo_pinned = false; -} - - -/** - * vmw_execbuf_release_pinned_bo - Flush queries and unpin the pinned - * query bo. - * - * @dev_priv: The device private structure. - * @only_on_cid_match: Only flush and unpin if the current active query cid - * matches @cid. - * @cid: Optional context id to match. - * - * This function should be used to unpin the pinned query bo, or - * as a query barrier when we need to make sure that all queries have - * finished before the next fifo command. (For example on hardware - * context destructions where the hardware may otherwise leak unfinished - * queries). - * - * This function does not return any failure codes, but make attempts - * to do safe unpinning in case of errors. - * - * The function will synchronize on the previous query barrier, and will - * thus not finish until that barrier has executed. - */ -void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, - bool only_on_cid_match, uint32_t cid) -{ - int ret = 0; - struct list_head validate_list; - struct ttm_validate_buffer pinned_val, query_val; - struct vmw_fence_obj *fence; - - mutex_lock(&dev_priv->cmdbuf_mutex); - - if (dev_priv->pinned_bo == NULL) - goto out_unlock; - - if (only_on_cid_match && cid != dev_priv->query_cid) - goto out_unlock; - - INIT_LIST_HEAD(&validate_list); - - pinned_val.new_sync_obj_arg = (void *)(unsigned long) - DRM_VMW_FENCE_FLAG_EXEC; - pinned_val.bo = ttm_bo_reference(dev_priv->pinned_bo); - list_add_tail(&pinned_val.head, &validate_list); - - query_val.new_sync_obj_arg = pinned_val.new_sync_obj_arg; - query_val.bo = ttm_bo_reference(dev_priv->dummy_query_bo); - list_add_tail(&query_val.head, &validate_list); - - do { - ret = ttm_eu_reserve_buffers(&validate_list); - } while (ret == -ERESTARTSYS); - - if (unlikely(ret != 0)) { - vmw_execbuf_unpin_panic(dev_priv); - goto out_no_reserve; - } - - ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid); - if (unlikely(ret != 0)) { - vmw_execbuf_unpin_panic(dev_priv); - goto out_no_emit; - } - - vmw_bo_pin(dev_priv->pinned_bo, false); - vmw_bo_pin(dev_priv->dummy_query_bo, false); - dev_priv->dummy_query_bo_pinned = false; - - (void) vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); - ttm_eu_fence_buffer_objects(&validate_list, (void *) fence); - - ttm_bo_unref(&query_val.bo); - ttm_bo_unref(&pinned_val.bo); - ttm_bo_unref(&dev_priv->pinned_bo); - -out_unlock: - mutex_unlock(&dev_priv->cmdbuf_mutex); - return; - -out_no_emit: - ttm_eu_backoff_reservation(&validate_list); -out_no_reserve: - ttm_bo_unref(&query_val.bo); - ttm_bo_unref(&pinned_val.bo); - ttm_bo_unref(&dev_priv->pinned_bo); - mutex_unlock(&dev_priv->cmdbuf_mutex); -} - - -int vmw_execbuf_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_vmw_execbuf_arg *arg = (struct drm_vmw_execbuf_arg *)data; - struct vmw_master *vmaster = vmw_master(file_priv->master); - int ret; - - /* - * This will allow us to extend the ioctl argument while - * maintaining backwards compatibility: - * We take different code paths depending on the value of - * arg->version. - */ - - if (unlikely(arg->version != DRM_VMW_EXECBUF_VERSION)) { - DRM_ERROR("Incorrect execbuf version.\n"); - DRM_ERROR("You're running outdated experimental " - "vmwgfx user-space drivers."); - return -EINVAL; - } - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - return ret; - - ret = vmw_execbuf_process(file_priv, dev_priv, - (void __user *)(unsigned long)arg->commands, - NULL, arg->command_size, arg->throttle_us, - (void __user *)(unsigned long)arg->fence_rep); - - if (unlikely(ret != 0)) - goto out_unlock; - - vmw_kms_cursor_post_execbuf(dev_priv); - -out_unlock: +out_no_cmd_mutex: ttm_read_unlock(&vmaster->lock); return ret; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 070797b7b03a..b1888e801e22 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -592,6 +592,58 @@ int vmw_fb_close(struct vmw_private *vmw_priv) return 0; } +int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv, + struct vmw_dma_buffer *vmw_bo) +{ + struct ttm_buffer_object *bo = &vmw_bo->base; + int ret = 0; + + ret = ttm_bo_reserve(bo, false, false, false, 0); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_bo_validate(bo, &vmw_sys_placement, false, false, false); + ttm_bo_unreserve(bo); + + return ret; +} + +int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, + struct vmw_dma_buffer *vmw_bo) +{ + struct ttm_buffer_object *bo = &vmw_bo->base; + struct ttm_placement ne_placement = vmw_vram_ne_placement; + int ret = 0; + + ne_placement.lpfn = bo->num_pages; + + /* interuptable? */ + ret = ttm_write_lock(&vmw_priv->active_master->lock, false); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_bo_reserve(bo, false, false, false, 0); + if (unlikely(ret != 0)) + goto err_unlock; + + if (bo->mem.mem_type == TTM_PL_VRAM && + bo->mem.start < bo->num_pages && + bo->mem.start > 0) + (void) ttm_bo_validate(bo, &vmw_sys_placement, false, + false, false); + + ret = ttm_bo_validate(bo, &ne_placement, false, false, false); + + /* Could probably bug on */ + WARN_ON(bo->offset != 0); + + ttm_bo_unreserve(bo); +err_unlock: + ttm_write_unlock(&vmw_priv->active_master->lock); + + return ret; +} + int vmw_fb_off(struct vmw_private *vmw_priv) { struct fb_info *info; @@ -613,7 +665,7 @@ int vmw_fb_off(struct vmw_private *vmw_priv) par->bo_ptr = NULL; ttm_bo_kunmap(&par->map); - vmw_dmabuf_unpin(vmw_priv, par->vmw_bo, false); + vmw_dmabuf_from_vram(vmw_priv, par->vmw_bo); return 0; } @@ -639,7 +691,7 @@ int vmw_fb_on(struct vmw_private *vmw_priv) /* Make sure that all overlays are stoped when we take over */ vmw_overlay_stop_all(vmw_priv); - ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo, true, false); + ret = vmw_dmabuf_to_start_of_vram(vmw_priv, par->vmw_bo); if (unlikely(ret != 0)) { DRM_ERROR("could not move buffer to start of VRAM\n"); goto err_no_buffer; diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 35d5f61fc7e4..5065a140fdf8 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -34,18 +34,13 @@ struct vmw_fence_manager { int num_fence_objects; struct vmw_private *dev_priv; spinlock_t lock; + u32 next_seqno; struct list_head fence_list; struct work_struct work; u32 user_fence_size; u32 fence_size; - u32 event_fence_action_size; bool fifo_down; struct list_head cleanup_list; - uint32_t pending_actions[VMW_ACTION_MAX]; - struct mutex goal_irq_mutex; - bool goal_irq_on; /* Protected by @goal_irq_mutex */ - bool seqno_valid; /* Protected by @lock, and may not be set to true - without the @goal_irq_mutex held. */ }; struct vmw_user_fence { @@ -54,51 +49,8 @@ struct vmw_user_fence { }; /** - * struct vmw_event_fence_action - fence action that delivers a drm event. + * vmw_fence_destroy_locked * - * @e: A struct drm_pending_event that controls the event delivery. - * @action: A struct vmw_fence_action to hook up to a fence. - * @fence: A referenced pointer to the fence to keep it alive while @action - * hangs on it. - * @dev: Pointer to a struct drm_device so we can access the event stuff. - * @kref: Both @e and @action has destructors, so we need to refcount. - * @size: Size accounted for this object. - * @tv_sec: If non-null, the variable pointed to will be assigned - * current time tv_sec val when the fence signals. - * @tv_usec: Must be set if @tv_sec is set, and the variable pointed to will - * be assigned the current time tv_usec val when the fence signals. - */ -struct vmw_event_fence_action { - struct drm_pending_event e; - struct vmw_fence_action action; - struct vmw_fence_obj *fence; - struct drm_device *dev; - struct kref kref; - uint32_t size; - uint32_t *tv_sec; - uint32_t *tv_usec; -}; - -/** - * Note on fencing subsystem usage of irqs: - * Typically the vmw_fences_update function is called - * - * a) When a new fence seqno has been submitted by the fifo code. - * b) On-demand when we have waiters. Sleeping waiters will switch on the - * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE - * irq is received. When the last fence waiter is gone, that IRQ is masked - * away. - * - * In situations where there are no waiters and we don't submit any new fences, - * fence objects may not be signaled. This is perfectly OK, since there are - * no consumers of the signaled data, but that is NOT ok when there are fence - * actions attached to a fence. The fencing subsystem then makes use of the - * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence - * which has an action attached, and each time vmw_fences_update is called, - * the subsystem makes sure the fence goal seqno is updated. - * - * The fence goal seqno irq is on as long as there are unsignaled fence - * objects with actions attached to them. */ static void vmw_fence_obj_destroy_locked(struct kref *kref) @@ -133,36 +85,24 @@ static void vmw_fence_work_func(struct work_struct *work) container_of(work, struct vmw_fence_manager, work); struct list_head list; struct vmw_fence_action *action, *next_action; - bool seqno_valid; do { INIT_LIST_HEAD(&list); - mutex_lock(&fman->goal_irq_mutex); - spin_lock_irq(&fman->lock); list_splice_init(&fman->cleanup_list, &list); - seqno_valid = fman->seqno_valid; spin_unlock_irq(&fman->lock); - if (!seqno_valid && fman->goal_irq_on) { - fman->goal_irq_on = false; - vmw_goal_waiter_remove(fman->dev_priv); - } - mutex_unlock(&fman->goal_irq_mutex); - if (list_empty(&list)) return; /* * At this point, only we should be able to manipulate the * list heads of the actions we have on the private list. - * hence fman::lock not held. */ list_for_each_entry_safe(action, next_action, &list, head) { list_del_init(&action->head); - if (action->cleanup) - action->cleanup(action); + action->cleanup(action); } } while (1); } @@ -182,9 +122,6 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) fman->fifo_down = true; fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); - fman->event_fence_action_size = - ttm_round_pot(sizeof(struct vmw_event_fence_action)); - mutex_init(&fman->goal_irq_mutex); return fman; } @@ -240,9 +177,6 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, struct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence) { - if (unlikely(fence == NULL)) - return NULL; - kref_get(&fence->kref); return fence; } @@ -257,12 +191,8 @@ struct vmw_fence_obj *vmw_fence_obj_reference(struct vmw_fence_obj *fence) void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p) { struct vmw_fence_obj *fence = *fence_p; - struct vmw_fence_manager *fman; - - if (unlikely(fence == NULL)) - return; + struct vmw_fence_manager *fman = fence->fman; - fman = fence->fman; *fence_p = NULL; spin_lock_irq(&fman->lock); BUG_ON(atomic_read(&fence->kref.refcount) == 0); @@ -277,7 +207,6 @@ void vmw_fences_perform_actions(struct vmw_fence_manager *fman, list_for_each_entry_safe(action, next_action, list, head) { list_del_init(&action->head); - fman->pending_actions[action->type]--; if (action->seq_passed != NULL) action->seq_passed(action); @@ -286,101 +215,17 @@ void vmw_fences_perform_actions(struct vmw_fence_manager *fman, * it will be performed by a worker task. */ - list_add_tail(&action->head, &fman->cleanup_list); + if (action->cleanup != NULL) + list_add_tail(&action->head, &fman->cleanup_list); } } -/** - * vmw_fence_goal_new_locked - Figure out a new device fence goal - * seqno if needed. - * - * @fman: Pointer to a fence manager. - * @passed_seqno: The seqno the device currently signals as passed. - * - * This function should be called with the fence manager lock held. - * It is typically called when we have a new passed_seqno, and - * we might need to update the fence goal. It checks to see whether - * the current fence goal has already passed, and, in that case, - * scans through all unsignaled fences to get the next fence object with an - * action attached, and sets the seqno of that fence as a new fence goal. - * - * returns true if the device goal seqno was updated. False otherwise. - */ -static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, - u32 passed_seqno) -{ - u32 goal_seqno; - __le32 __iomem *fifo_mem; - struct vmw_fence_obj *fence; - - if (likely(!fman->seqno_valid)) - return false; - - fifo_mem = fman->dev_priv->mmio_virt; - goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL); - if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) - return false; - - fman->seqno_valid = false; - list_for_each_entry(fence, &fman->fence_list, head) { - if (!list_empty(&fence->seq_passed_actions)) { - fman->seqno_valid = true; - iowrite32(fence->seqno, - fifo_mem + SVGA_FIFO_FENCE_GOAL); - break; - } - } - - return true; -} - - -/** - * vmw_fence_goal_check_locked - Replace the device fence goal seqno if - * needed. - * - * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be - * considered as a device fence goal. - * - * This function should be called with the fence manager lock held. - * It is typically called when an action has been attached to a fence to - * check whether the seqno of that fence should be used for a fence - * goal interrupt. This is typically needed if the current fence goal is - * invalid, or has a higher seqno than that of the current fence object. - * - * returns true if the device goal seqno was updated. False otherwise. - */ -static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) -{ - u32 goal_seqno; - __le32 __iomem *fifo_mem; - - if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) - return false; - - fifo_mem = fence->fman->dev_priv->mmio_virt; - goal_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE_GOAL); - if (likely(fence->fman->seqno_valid && - goal_seqno - fence->seqno < VMW_FENCE_WRAP)) - return false; - - iowrite32(fence->seqno, fifo_mem + SVGA_FIFO_FENCE_GOAL); - fence->fman->seqno_valid = true; - - return true; -} - -void vmw_fences_update(struct vmw_fence_manager *fman) +void vmw_fences_update(struct vmw_fence_manager *fman, u32 seqno) { unsigned long flags; struct vmw_fence_obj *fence, *next_fence; struct list_head action_list; - bool needs_rerun; - uint32_t seqno, new_seqno; - __le32 __iomem *fifo_mem = fman->dev_priv->mmio_virt; - seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); -rerun: spin_lock_irqsave(&fman->lock, flags); list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { if (seqno - fence->seqno < VMW_FENCE_WRAP) { @@ -391,31 +236,15 @@ void vmw_fences_update(struct vmw_fence_manager *fman) &action_list); vmw_fences_perform_actions(fman, &action_list); wake_up_all(&fence->queue); - } else - break; - } - - needs_rerun = vmw_fence_goal_new_locked(fman, seqno); + } + } if (!list_empty(&fman->cleanup_list)) (void) schedule_work(&fman->work); spin_unlock_irqrestore(&fman->lock, flags); - - /* - * Rerun if the fence goal seqno was updated, and the - * hardware might have raced with that update, so that - * we missed a fence_goal irq. - */ - - if (unlikely(needs_rerun)) { - new_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); - if (new_seqno != seqno) { - seqno = new_seqno; - goto rerun; - } - } } + bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence, uint32_t flags) { @@ -431,8 +260,14 @@ bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence, if ((signaled & flags) == flags) return 1; - if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0) - vmw_fences_update(fman); + if ((signaled & DRM_VMW_FENCE_FLAG_EXEC) == 0) { + struct vmw_private *dev_priv = fman->dev_priv; + __le32 __iomem *fifo_mem = dev_priv->mmio_virt; + u32 seqno; + + seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); + vmw_fences_update(fman, seqno); + } spin_lock_irqsave(&fman->lock, irq_flags); signaled = fence->signaled; @@ -782,344 +617,3 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, arg->handle, TTM_REF_USAGE); } - -/** - * vmw_event_fence_action_destroy - * - * @kref: The struct kref embedded in a struct vmw_event_fence_action. - * - * The vmw_event_fence_action destructor that may be called either after - * the fence action cleanup, or when the event is delivered. - * It frees both the vmw_event_fence_action struct and the actual - * event structure copied to user-space. - */ -static void vmw_event_fence_action_destroy(struct kref *kref) -{ - struct vmw_event_fence_action *eaction = - container_of(kref, struct vmw_event_fence_action, kref); - struct ttm_mem_global *mem_glob = - vmw_mem_glob(vmw_priv(eaction->dev)); - uint32_t size = eaction->size; - - kfree(eaction->e.event); - kfree(eaction); - ttm_mem_global_free(mem_glob, size); -} - - -/** - * vmw_event_fence_action_delivered - * - * @e: The struct drm_pending_event embedded in a struct - * vmw_event_fence_action. - * - * The struct drm_pending_event destructor that is called by drm - * once the event is delivered. Since we don't know whether this function - * will be called before or after the fence action destructor, we - * free a refcount and destroy if it becomes zero. - */ -static void vmw_event_fence_action_delivered(struct drm_pending_event *e) -{ - struct vmw_event_fence_action *eaction = - container_of(e, struct vmw_event_fence_action, e); - - kref_put(&eaction->kref, vmw_event_fence_action_destroy); -} - - -/** - * vmw_event_fence_action_seq_passed - * - * @action: The struct vmw_fence_action embedded in a struct - * vmw_event_fence_action. - * - * This function is called when the seqno of the fence where @action is - * attached has passed. It queues the event on the submitter's event list. - * This function is always called from atomic context, and may be called - * from irq context. It ups a refcount reflecting that we now have two - * destructors. - */ -static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) -{ - struct vmw_event_fence_action *eaction = - container_of(action, struct vmw_event_fence_action, action); - struct drm_device *dev = eaction->dev; - struct drm_file *file_priv = eaction->e.file_priv; - unsigned long irq_flags; - - kref_get(&eaction->kref); - spin_lock_irqsave(&dev->event_lock, irq_flags); - - if (likely(eaction->tv_sec != NULL)) { - struct timeval tv; - - do_gettimeofday(&tv); - *eaction->tv_sec = tv.tv_sec; - *eaction->tv_usec = tv.tv_usec; - } - - list_add_tail(&eaction->e.link, &file_priv->event_list); - wake_up_all(&file_priv->event_wait); - spin_unlock_irqrestore(&dev->event_lock, irq_flags); -} - -/** - * vmw_event_fence_action_cleanup - * - * @action: The struct vmw_fence_action embedded in a struct - * vmw_event_fence_action. - * - * This function is the struct vmw_fence_action destructor. It's typically - * called from a workqueue. - */ -static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) -{ - struct vmw_event_fence_action *eaction = - container_of(action, struct vmw_event_fence_action, action); - - vmw_fence_obj_unreference(&eaction->fence); - kref_put(&eaction->kref, vmw_event_fence_action_destroy); -} - - -/** - * vmw_fence_obj_add_action - Add an action to a fence object. - * - * @fence - The fence object. - * @action - The action to add. - * - * Note that the action callbacks may be executed before this function - * returns. - */ -void vmw_fence_obj_add_action(struct vmw_fence_obj *fence, - struct vmw_fence_action *action) -{ - struct vmw_fence_manager *fman = fence->fman; - unsigned long irq_flags; - bool run_update = false; - - mutex_lock(&fman->goal_irq_mutex); - spin_lock_irqsave(&fman->lock, irq_flags); - - fman->pending_actions[action->type]++; - if (fence->signaled & DRM_VMW_FENCE_FLAG_EXEC) { - struct list_head action_list; - - INIT_LIST_HEAD(&action_list); - list_add_tail(&action->head, &action_list); - vmw_fences_perform_actions(fman, &action_list); - } else { - list_add_tail(&action->head, &fence->seq_passed_actions); - - /* - * This function may set fman::seqno_valid, so it must - * be run with the goal_irq_mutex held. - */ - run_update = vmw_fence_goal_check_locked(fence); - } - - spin_unlock_irqrestore(&fman->lock, irq_flags); - - if (run_update) { - if (!fman->goal_irq_on) { - fman->goal_irq_on = true; - vmw_goal_waiter_add(fman->dev_priv); - } - vmw_fences_update(fman); - } - mutex_unlock(&fman->goal_irq_mutex); - -} - -/** - * vmw_event_fence_action_create - Post an event for sending when a fence - * object seqno has passed. - * - * @file_priv: The file connection on which the event should be posted. - * @fence: The fence object on which to post the event. - * @event: Event to be posted. This event should've been alloced - * using k[mz]alloc, and should've been completely initialized. - * @interruptible: Interruptible waits if possible. - * - * As a side effect, the object pointed to by @event may have been - * freed when this function returns. If this function returns with - * an error code, the caller needs to free that object. - */ - -int vmw_event_fence_action_create(struct drm_file *file_priv, - struct vmw_fence_obj *fence, - struct drm_event *event, - uint32_t *tv_sec, - uint32_t *tv_usec, - bool interruptible) -{ - struct vmw_event_fence_action *eaction = - kzalloc(sizeof(*eaction), GFP_KERNEL); - struct ttm_mem_global *mem_glob = - vmw_mem_glob(fence->fman->dev_priv); - struct vmw_fence_manager *fman = fence->fman; - uint32_t size = fman->event_fence_action_size + - ttm_round_pot(event->length); - int ret; - - /* - * Account for internal structure size as well as the - * event size itself. - */ - - ret = ttm_mem_global_alloc(mem_glob, size, false, interruptible); - if (unlikely(ret != 0)) - return ret; - - eaction = kzalloc(sizeof(*eaction), GFP_KERNEL); - if (unlikely(eaction == NULL)) { - ttm_mem_global_free(mem_glob, size); - return -ENOMEM; - } - - eaction->e.event = event; - eaction->e.file_priv = file_priv; - eaction->e.destroy = vmw_event_fence_action_delivered; - - eaction->action.seq_passed = vmw_event_fence_action_seq_passed; - eaction->action.cleanup = vmw_event_fence_action_cleanup; - eaction->action.type = VMW_ACTION_EVENT; - - eaction->fence = vmw_fence_obj_reference(fence); - eaction->dev = fman->dev_priv->dev; - eaction->size = size; - eaction->tv_sec = tv_sec; - eaction->tv_usec = tv_usec; - - kref_init(&eaction->kref); - vmw_fence_obj_add_action(fence, &eaction->action); - - return 0; -} - -int vmw_fence_event_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_vmw_fence_event_arg *arg = - (struct drm_vmw_fence_event_arg *) data; - struct vmw_fence_obj *fence = NULL; - struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); - struct drm_vmw_fence_rep __user *user_fence_rep = - (struct drm_vmw_fence_rep __user *)(unsigned long) - arg->fence_rep; - uint32_t handle; - unsigned long irq_flags; - struct drm_vmw_event_fence *event; - int ret; - - /* - * Look up an existing fence object, - * and if user-space wants a new reference, - * add one. - */ - if (arg->handle) { - struct ttm_base_object *base = - ttm_base_object_lookup(vmw_fp->tfile, arg->handle); - - if (unlikely(base == NULL)) { - DRM_ERROR("Fence event invalid fence object handle " - "0x%08lx.\n", - (unsigned long)arg->handle); - return -EINVAL; - } - fence = &(container_of(base, struct vmw_user_fence, - base)->fence); - (void) vmw_fence_obj_reference(fence); - - if (user_fence_rep != NULL) { - bool existed; - - ret = ttm_ref_object_add(vmw_fp->tfile, base, - TTM_REF_USAGE, &existed); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to reference a fence " - "object.\n"); - goto out_no_ref_obj; - } - handle = base->hash.key; - } - ttm_base_object_unref(&base); - } - - /* - * Create a new fence object. - */ - if (!fence) { - ret = vmw_execbuf_fence_commands(file_priv, dev_priv, - &fence, - (user_fence_rep) ? - &handle : NULL); - if (unlikely(ret != 0)) { - DRM_ERROR("Fence event failed to create fence.\n"); - return ret; - } - } - - BUG_ON(fence == NULL); - - spin_lock_irqsave(&dev->event_lock, irq_flags); - - ret = (file_priv->event_space < sizeof(*event)) ? -EBUSY : 0; - if (likely(ret == 0)) - file_priv->event_space -= sizeof(*event); - - spin_unlock_irqrestore(&dev->event_lock, irq_flags); - - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to allocate event space for this file.\n"); - goto out_no_event_space; - } - - event = kzalloc(sizeof(*event), GFP_KERNEL); - if (unlikely(event == NULL)) { - DRM_ERROR("Failed to allocate an event.\n"); - goto out_no_event; - } - - event->base.type = DRM_VMW_EVENT_FENCE_SIGNALED; - event->base.length = sizeof(*event); - event->user_data = arg->user_data; - - if (arg->flags & DRM_VMW_FE_FLAG_REQ_TIME) - ret = vmw_event_fence_action_create(file_priv, fence, - &event->base, - &event->tv_sec, - &event->tv_usec, - true); - else - ret = vmw_event_fence_action_create(file_priv, fence, - &event->base, - NULL, - NULL, - true); - - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Failed to attach event to fence.\n"); - goto out_no_attach; - } - - vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence, - handle); - vmw_fence_obj_unreference(&fence); - return 0; -out_no_attach: - kfree(event); -out_no_event: - spin_lock_irqsave(&dev->event_lock, irq_flags); - file_priv->event_space += sizeof(*event); - spin_unlock_irqrestore(&dev->event_lock, irq_flags); -out_no_event_space: - if (user_fence_rep != NULL) - ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, - handle, TTM_REF_USAGE); -out_no_ref_obj: - vmw_fence_obj_unreference(&fence); - return ret; -} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index 0854a2096b55..93074064aaf3 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -37,14 +37,8 @@ struct vmw_fence_manager; * * */ -enum vmw_action_type { - VMW_ACTION_EVENT = 0, - VMW_ACTION_MAX -}; - struct vmw_fence_action { struct list_head head; - enum vmw_action_type type; void (*seq_passed) (struct vmw_fence_action *action); void (*cleanup) (struct vmw_fence_action *action); }; @@ -72,7 +66,8 @@ extern void vmw_fence_obj_unreference(struct vmw_fence_obj **fence_p); extern struct vmw_fence_obj * vmw_fence_obj_reference(struct vmw_fence_obj *fence); -extern void vmw_fences_update(struct vmw_fence_manager *fman); +extern void vmw_fences_update(struct vmw_fence_manager *fman, + u32 sequence); extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence, uint32_t flags); @@ -107,7 +102,4 @@ extern int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data, extern int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int vmw_fence_event_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); - #endif /* _VMWGFX_FENCE_H_ */ diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 03bbc2a6f9a7..3ba9cac579e0 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -45,11 +45,7 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) if (hwversion == 0) return false; - if (hwversion < SVGA3D_HWVERSION_WS8_B1) - return false; - - /* Non-Screen Object path does not support surfaces */ - if (!dev_priv->sou_priv) + if (hwversion < SVGA3D_HWVERSION_WS65_B1) return false; return true; @@ -247,8 +243,9 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); outl(SVGA_IRQFLAG_FIFO_PROGRESS, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); - dev_priv->irq_mask |= SVGA_IRQFLAG_FIFO_PROGRESS; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + vmw_write(dev_priv, SVGA_REG_IRQMASK, + vmw_read(dev_priv, SVGA_REG_IRQMASK) | + SVGA_IRQFLAG_FIFO_PROGRESS); spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); } mutex_unlock(&dev_priv->hw_mutex); @@ -270,8 +267,9 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, mutex_lock(&dev_priv->hw_mutex); if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); - dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + vmw_write(dev_priv, SVGA_REG_IRQMASK, + vmw_read(dev_priv, SVGA_REG_IRQMASK) & + ~SVGA_IRQFLAG_FIFO_PROGRESS); spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); } mutex_unlock(&dev_priv->hw_mutex); @@ -279,16 +277,6 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, return ret; } -/** - * Reserve @bytes number of bytes in the fifo. - * - * This function will return NULL (error) on two conditions: - * If it timeouts waiting for fifo space, or if @bytes is larger than the - * available fifo space. - * - * Returns: - * Pointer to the fifo, or null on error (possible hardware hang). - */ void *vmw_fifo_reserve(struct vmw_private *dev_priv, uint32_t bytes) { struct vmw_fifo_state *fifo_state = &dev_priv->fifo; @@ -503,60 +491,3 @@ int vmw_fifo_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) out_err: return ret; } - -/** - * vmw_fifo_emit_dummy_query - emits a dummy query to the fifo. - * - * @dev_priv: The device private structure. - * @cid: The hardware context id used for the query. - * - * This function is used to emit a dummy occlusion query with - * no primitives rendered between query begin and query end. - * It's used to provide a query barrier, in order to know that when - * this query is finished, all preceding queries are also finished. - * - * A Query results structure should have been initialized at the start - * of the dev_priv->dummy_query_bo buffer object. And that buffer object - * must also be either reserved or pinned when this function is called. - * - * Returns -ENOMEM on failure to reserve fifo space. - */ -int vmw_fifo_emit_dummy_query(struct vmw_private *dev_priv, - uint32_t cid) -{ - /* - * A query wait without a preceding query end will - * actually finish all queries for this cid - * without writing to the query result structure. - */ - - struct ttm_buffer_object *bo = dev_priv->dummy_query_bo; - struct { - SVGA3dCmdHeader header; - SVGA3dCmdWaitForQuery body; - } *cmd; - - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - - if (unlikely(cmd == NULL)) { - DRM_ERROR("Out of fifo space for dummy query.\n"); - return -ENOMEM; - } - - cmd->header.id = SVGA_3D_CMD_WAIT_FOR_QUERY; - cmd->header.size = sizeof(cmd->body); - cmd->body.cid = cid; - cmd->body.type = SVGA3D_QUERYTYPE_OCCLUSION; - - if (bo->mem.mem_type == TTM_PL_VRAM) { - cmd->body.guestResult.gmrId = SVGA_GMR_FRAMEBUFFER; - cmd->body.guestResult.offset = bo->offset; - } else { - cmd->body.guestResult.gmrId = bo->mem.start; - cmd->body.guestResult.offset = 0; - } - - vmw_fifo_commit(dev_priv, sizeof(*cmd)); - - return 0; -} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 97f23abeacda..5ecf96660644 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -27,7 +27,6 @@ #include "vmwgfx_drv.h" #include "vmwgfx_drm.h" -#include "vmwgfx_kms.h" int vmw_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -111,217 +110,3 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, return ret; } - -int vmw_present_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_vmw_present_arg *arg = - (struct drm_vmw_present_arg *)data; - struct vmw_surface *surface; - struct vmw_master *vmaster = vmw_master(file_priv->master); - struct drm_vmw_rect __user *clips_ptr; - struct drm_vmw_rect *clips = NULL; - struct drm_mode_object *obj; - struct vmw_framebuffer *vfb; - uint32_t num_clips; - int ret; - - num_clips = arg->num_clips; - clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; - - if (unlikely(num_clips == 0)) - return 0; - - if (clips_ptr == NULL) { - DRM_ERROR("Variable clips_ptr must be specified.\n"); - ret = -EINVAL; - goto out_clips; - } - - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); - if (clips == NULL) { - DRM_ERROR("Failed to allocate clip rect list.\n"); - ret = -ENOMEM; - goto out_clips; - } - - ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips)); - if (ret) { - DRM_ERROR("Failed to copy clip rects from userspace.\n"); - goto out_no_copy; - } - - ret = mutex_lock_interruptible(&dev->mode_config.mutex); - if (unlikely(ret != 0)) { - ret = -ERESTARTSYS; - goto out_no_mode_mutex; - } - - obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); - if (!obj) { - DRM_ERROR("Invalid framebuffer id.\n"); - ret = -EINVAL; - goto out_no_fb; - } - - vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj)); - if (!vfb->dmabuf) { - DRM_ERROR("Framebuffer not dmabuf backed.\n"); - ret = -EINVAL; - goto out_no_fb; - } - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - goto out_no_ttm_lock; - - ret = vmw_user_surface_lookup_handle(dev_priv, tfile, arg->sid, - &surface); - if (ret) - goto out_no_surface; - - ret = vmw_kms_present(dev_priv, file_priv, - vfb, surface, arg->sid, - arg->dest_x, arg->dest_y, - clips, num_clips); - - /* vmw_user_surface_lookup takes one ref so does new_fb */ - vmw_surface_unreference(&surface); - -out_no_surface: - ttm_read_unlock(&vmaster->lock); -out_no_ttm_lock: -out_no_fb: - mutex_unlock(&dev->mode_config.mutex); -out_no_mode_mutex: -out_no_copy: - kfree(clips); -out_clips: - return ret; -} - -int vmw_present_readback_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_vmw_present_readback_arg *arg = - (struct drm_vmw_present_readback_arg *)data; - struct drm_vmw_fence_rep __user *user_fence_rep = - (struct drm_vmw_fence_rep __user *) - (unsigned long)arg->fence_rep; - struct vmw_master *vmaster = vmw_master(file_priv->master); - struct drm_vmw_rect __user *clips_ptr; - struct drm_vmw_rect *clips = NULL; - struct drm_mode_object *obj; - struct vmw_framebuffer *vfb; - uint32_t num_clips; - int ret; - - num_clips = arg->num_clips; - clips_ptr = (struct drm_vmw_rect *)(unsigned long)arg->clips_ptr; - - if (unlikely(num_clips == 0)) - return 0; - - if (clips_ptr == NULL) { - DRM_ERROR("Argument clips_ptr must be specified.\n"); - ret = -EINVAL; - goto out_clips; - } - - clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); - if (clips == NULL) { - DRM_ERROR("Failed to allocate clip rect list.\n"); - ret = -ENOMEM; - goto out_clips; - } - - ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips)); - if (ret) { - DRM_ERROR("Failed to copy clip rects from userspace.\n"); - goto out_no_copy; - } - - ret = mutex_lock_interruptible(&dev->mode_config.mutex); - if (unlikely(ret != 0)) { - ret = -ERESTARTSYS; - goto out_no_mode_mutex; - } - - obj = drm_mode_object_find(dev, arg->fb_id, DRM_MODE_OBJECT_FB); - if (!obj) { - DRM_ERROR("Invalid framebuffer id.\n"); - ret = -EINVAL; - goto out_no_fb; - } - - vfb = vmw_framebuffer_to_vfb(obj_to_fb(obj)); - if (!vfb->dmabuf) { - DRM_ERROR("Framebuffer not dmabuf backed.\n"); - ret = -EINVAL; - goto out_no_fb; - } - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - goto out_no_ttm_lock; - - ret = vmw_kms_readback(dev_priv, file_priv, - vfb, user_fence_rep, - clips, num_clips); - - ttm_read_unlock(&vmaster->lock); -out_no_ttm_lock: -out_no_fb: - mutex_unlock(&dev->mode_config.mutex); -out_no_mode_mutex: -out_no_copy: - kfree(clips); -out_clips: - return ret; -} - - -/** - * vmw_fops_poll - wrapper around the drm_poll function - * - * @filp: See the linux fops poll documentation. - * @wait: See the linux fops poll documentation. - * - * Wrapper around the drm_poll function that makes sure the device is - * processing the fifo if drm_poll decides to wait. - */ -unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait) -{ - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = - vmw_priv(file_priv->minor->dev); - - vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); - return drm_poll(filp, wait); -} - - -/** - * vmw_fops_read - wrapper around the drm_read function - * - * @filp: See the linux fops read documentation. - * @buffer: See the linux fops read documentation. - * @count: See the linux fops read documentation. - * offset: See the linux fops read documentation. - * - * Wrapper around the drm_read function that makes sure the device is - * processing the fifo if drm_read decides to wait. - */ -ssize_t vmw_fops_read(struct file *filp, char __user *buffer, - size_t count, loff_t *offset) -{ - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = - vmw_priv(file_priv->minor->dev); - - vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); - return drm_read(filp, buffer, count, offset); -} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index cabc95f7517e..a005292a8908 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -34,30 +34,28 @@ irqreturn_t vmw_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *)arg; struct vmw_private *dev_priv = vmw_priv(dev); - uint32_t status, masked_status; + uint32_t status; spin_lock(&dev_priv->irq_lock); status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); - masked_status = status & dev_priv->irq_mask; spin_unlock(&dev_priv->irq_lock); - if (likely(status)) - outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); - - if (!masked_status) - return IRQ_NONE; + if (status & SVGA_IRQFLAG_ANY_FENCE) { + __le32 __iomem *fifo_mem = dev_priv->mmio_virt; + uint32_t seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE); - if (masked_status & (SVGA_IRQFLAG_ANY_FENCE | - SVGA_IRQFLAG_FENCE_GOAL)) { - vmw_fences_update(dev_priv->fman); + vmw_fences_update(dev_priv->fman, seqno); wake_up_all(&dev_priv->fence_queue); } - - if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS) + if (status & SVGA_IRQFLAG_FIFO_PROGRESS) wake_up_all(&dev_priv->fifo_queue); + if (likely(status)) { + outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); + return IRQ_HANDLED; + } - return IRQ_HANDLED; + return IRQ_NONE; } static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) @@ -80,7 +78,7 @@ void vmw_update_seqno(struct vmw_private *dev_priv, if (dev_priv->last_read_seqno != seqno) { dev_priv->last_read_seqno = seqno; vmw_marker_pull(&fifo_state->marker_queue, seqno); - vmw_fences_update(dev_priv->fman); + vmw_fences_update(dev_priv->fman, seqno); } } @@ -191,8 +189,9 @@ void vmw_seqno_waiter_add(struct vmw_private *dev_priv) spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); outl(SVGA_IRQFLAG_ANY_FENCE, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); - dev_priv->irq_mask |= SVGA_IRQFLAG_ANY_FENCE; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + vmw_write(dev_priv, SVGA_REG_IRQMASK, + vmw_read(dev_priv, SVGA_REG_IRQMASK) | + SVGA_IRQFLAG_ANY_FENCE); spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); } mutex_unlock(&dev_priv->hw_mutex); @@ -205,39 +204,9 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) unsigned long irq_flags; spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); - dev_priv->irq_mask &= ~SVGA_IRQFLAG_ANY_FENCE; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); - spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); - } - mutex_unlock(&dev_priv->hw_mutex); -} - - -void vmw_goal_waiter_add(struct vmw_private *dev_priv) -{ - mutex_lock(&dev_priv->hw_mutex); - if (dev_priv->goal_queue_waiters++ == 0) { - unsigned long irq_flags; - - spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); - outl(SVGA_IRQFLAG_FENCE_GOAL, - dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); - dev_priv->irq_mask |= SVGA_IRQFLAG_FENCE_GOAL; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); - spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); - } - mutex_unlock(&dev_priv->hw_mutex); -} - -void vmw_goal_waiter_remove(struct vmw_private *dev_priv) -{ - mutex_lock(&dev_priv->hw_mutex); - if (--dev_priv->goal_queue_waiters == 0) { - unsigned long irq_flags; - - spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); - dev_priv->irq_mask &= ~SVGA_IRQFLAG_FENCE_GOAL; - vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + vmw_write(dev_priv, SVGA_REG_IRQMASK, + vmw_read(dev_priv, SVGA_REG_IRQMASK) & + ~SVGA_IRQFLAG_ANY_FENCE); spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); } mutex_unlock(&dev_priv->hw_mutex); diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 2421d0cd0df9..1a4c84cecca7 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -27,10 +27,12 @@ #include "vmwgfx_kms.h" - /* Might need a hrtimer here? */ #define VMWGFX_PRESENT_RATE ((HZ / 60 > 0) ? HZ / 60 : 1) +static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb); +static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb); + void vmw_display_unit_cleanup(struct vmw_display_unit *du) { if (du->cursor_surface) @@ -327,10 +329,41 @@ struct vmw_framebuffer_surface { struct vmw_framebuffer base; struct vmw_surface *surface; struct vmw_dma_buffer *buffer; + struct delayed_work d_work; + struct mutex work_lock; + bool present_fs; struct list_head head; struct drm_master *master; }; +/** + * vmw_kms_idle_workqueues - Flush workqueues on this master + * + * @vmaster - Pointer identifying the master, for the surfaces of which + * we idle the dirty work queues. + * + * This function should be called with the ttm lock held in exclusive mode + * to idle all dirty work queues before the fifo is taken down. + * + * The work task may actually requeue itself, but after the flush returns we're + * sure that there's nothing to present, since the ttm lock is held in + * exclusive mode, so the fifo will never get used. + */ + +void vmw_kms_idle_workqueues(struct vmw_master *vmaster) +{ + struct vmw_framebuffer_surface *entry; + + mutex_lock(&vmaster->fb_surf_mutex); + list_for_each_entry(entry, &vmaster->fb_surf, head) { + if (cancel_delayed_work_sync(&entry->d_work)) + (void) entry->d_work.work.func(&entry->d_work.work); + + (void) cancel_delayed_work_sync(&entry->d_work); + } + mutex_unlock(&vmaster->fb_surf_mutex); +} + void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer) { struct vmw_framebuffer_surface *vfbs = @@ -342,130 +375,65 @@ void vmw_framebuffer_surface_destroy(struct drm_framebuffer *framebuffer) list_del(&vfbs->head); mutex_unlock(&vmaster->fb_surf_mutex); + cancel_delayed_work_sync(&vfbs->d_work); drm_master_put(&vfbs->master); drm_framebuffer_cleanup(framebuffer); vmw_surface_unreference(&vfbs->surface); - ttm_base_object_unref(&vfbs->base.user_obj); kfree(vfbs); } -static int do_surface_dirty_sou(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *framebuffer, - struct vmw_surface *surf, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips, int inc) +static void vmw_framebuffer_present_fs_callback(struct work_struct *work) { - struct drm_clip_rect *clips_ptr; - struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; - struct drm_crtc *crtc; - size_t fifo_size; - int i, num_units; - int ret = 0; /* silence warning */ - int left, right, top, bottom; + struct delayed_work *d_work = + container_of(work, struct delayed_work, work); + struct vmw_framebuffer_surface *vfbs = + container_of(d_work, struct vmw_framebuffer_surface, d_work); + struct vmw_surface *surf = vfbs->surface; + struct drm_framebuffer *framebuffer = &vfbs->base.base; + struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); struct { SVGA3dCmdHeader header; - SVGA3dCmdBlitSurfaceToScreen body; + SVGA3dCmdPresent body; + SVGA3dCopyRect cr; } *cmd; - SVGASignedRect *blits; - - - num_units = 0; - list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, - head) { - if (crtc->fb != &framebuffer->base) - continue; - units[num_units++] = vmw_crtc_to_du(crtc); - } - - BUG_ON(surf == NULL); - BUG_ON(!clips || !num_clips); - - fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips; - cmd = kzalloc(fifo_size, GFP_KERNEL); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Temporary fifo memory alloc failed.\n"); - return -ENOMEM; - } - - left = clips->x1; - right = clips->x2; - top = clips->y1; - bottom = clips->y2; - - clips_ptr = clips; - for (i = 1; i < num_clips; i++, clips_ptr += inc) { - left = min_t(int, left, (int)clips_ptr->x1); - right = max_t(int, right, (int)clips_ptr->x2); - top = min_t(int, top, (int)clips_ptr->y1); - bottom = max_t(int, bottom, (int)clips_ptr->y2); - } - - /* only need to do this once */ - memset(cmd, 0, fifo_size); - cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); - cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); - - cmd->body.srcRect.left = left; - cmd->body.srcRect.right = right; - cmd->body.srcRect.top = top; - cmd->body.srcRect.bottom = bottom; - - clips_ptr = clips; - blits = (SVGASignedRect *)&cmd[1]; - for (i = 0; i < num_clips; i++, clips_ptr += inc) { - blits[i].left = clips_ptr->x1 - left; - blits[i].right = clips_ptr->x2 - left; - blits[i].top = clips_ptr->y1 - top; - blits[i].bottom = clips_ptr->y2 - top; - } - - /* do per unit writing, reuse fifo for each */ - for (i = 0; i < num_units; i++) { - struct vmw_display_unit *unit = units[i]; - int clip_x1 = left - unit->crtc.x; - int clip_y1 = top - unit->crtc.y; - int clip_x2 = right - unit->crtc.x; - int clip_y2 = bottom - unit->crtc.y; - - /* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) - continue; - - /* need to reset sid as it is changed by execbuf */ - cmd->body.srcImage.sid = cpu_to_le32(framebuffer->user_handle); - - cmd->body.destScreenId = unit->unit; - - /* - * The blit command is a lot more resilient then the - * readback command when it comes to clip rects. So its - * okay to go out of bounds. - */ - - cmd->body.destRect.left = clip_x1; - cmd->body.destRect.right = clip_x2; - cmd->body.destRect.top = clip_y1; - cmd->body.destRect.bottom = clip_y2; - - - ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); - if (unlikely(ret != 0)) - break; - } - - kfree(cmd); - - return ret; + /** + * Strictly we should take the ttm_lock in read mode before accessing + * the fifo, to make sure the fifo is present and up. However, + * instead we flush all workqueues under the ttm lock in exclusive mode + * before taking down the fifo. + */ + mutex_lock(&vfbs->work_lock); + if (!vfbs->present_fs) + goto out_unlock; + + cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); + if (unlikely(cmd == NULL)) + goto out_resched; + + cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT); + cmd->header.size = cpu_to_le32(sizeof(cmd->body) + sizeof(cmd->cr)); + cmd->body.sid = cpu_to_le32(surf->res.id); + cmd->cr.x = cpu_to_le32(0); + cmd->cr.y = cpu_to_le32(0); + cmd->cr.srcx = cmd->cr.x; + cmd->cr.srcy = cmd->cr.y; + cmd->cr.w = cpu_to_le32(framebuffer->width); + cmd->cr.h = cpu_to_le32(framebuffer->height); + vfbs->present_fs = false; + vmw_fifo_commit(dev_priv, sizeof(*cmd)); +out_resched: + /** + * Will not re-add if already pending. + */ + schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE); +out_unlock: + mutex_unlock(&vfbs->work_lock); } + int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, struct drm_file *file_priv, unsigned flags, unsigned color, @@ -478,19 +446,42 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, vmw_framebuffer_to_vfbs(framebuffer); struct vmw_surface *surf = vfbs->surface; struct drm_clip_rect norect; - int ret, inc = 1; + SVGA3dCopyRect *cr; + int i, inc = 1; + int ret; - if (unlikely(vfbs->master != file_priv->master)) - return -EINVAL; + struct { + SVGA3dCmdHeader header; + SVGA3dCmdPresent body; + SVGA3dCopyRect cr; + } *cmd; - /* Require ScreenObject support for 3D */ - if (!dev_priv->sou_priv) + if (unlikely(vfbs->master != file_priv->master)) return -EINVAL; ret = ttm_read_lock(&vmaster->lock, true); if (unlikely(ret != 0)) return ret; + if (!num_clips || + !(dev_priv->fifo.capabilities & + SVGA_FIFO_CAP_SCREEN_OBJECT)) { + int ret; + + mutex_lock(&vfbs->work_lock); + vfbs->present_fs = true; + ret = schedule_delayed_work(&vfbs->d_work, VMWGFX_PRESENT_RATE); + mutex_unlock(&vfbs->work_lock); + if (ret) { + /** + * No work pending, Force immediate present. + */ + vmw_framebuffer_present_fs_callback(&vfbs->d_work.work); + } + ttm_read_unlock(&vmaster->lock); + return 0; + } + if (!num_clips) { num_clips = 1; clips = &norect; @@ -502,10 +493,29 @@ int vmw_framebuffer_surface_dirty(struct drm_framebuffer *framebuffer, inc = 2; /* skip source rects */ } - ret = do_surface_dirty_sou(dev_priv, file_priv, &vfbs->base, surf, - flags, color, - clips, num_clips, inc); + cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); + if (unlikely(cmd == NULL)) { + DRM_ERROR("Fifo reserve failed.\n"); + ttm_read_unlock(&vmaster->lock); + return -ENOMEM; + } + + memset(cmd, 0, sizeof(*cmd)); + cmd->header.id = cpu_to_le32(SVGA_3D_CMD_PRESENT); + cmd->header.size = cpu_to_le32(sizeof(cmd->body) + num_clips * sizeof(cmd->cr)); + cmd->body.sid = cpu_to_le32(surf->res.id); + + for (i = 0, cr = &cmd->cr; i < num_clips; i++, cr++, clips += inc) { + cr->x = cpu_to_le16(clips->x1); + cr->y = cpu_to_le16(clips->y1); + cr->srcx = cr->x; + cr->srcy = cr->y; + cr->w = cpu_to_le16(clips->x2 - clips->x1); + cr->h = cpu_to_le16(clips->y2 - clips->y1); + } + + vmw_fifo_commit(dev_priv, sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr)); ttm_read_unlock(&vmaster->lock); return 0; } @@ -530,10 +540,6 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, struct vmw_master *vmaster = vmw_master(file_priv->master); int ret; - /* 3D is only supported on HWv8 hosts which supports screen objects */ - if (!dev_priv->sou_priv) - return -ENOSYS; - /* * Sanity checks. */ @@ -596,11 +602,14 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, vfbs->base.base.depth = mode_cmd->depth; vfbs->base.base.width = mode_cmd->width; vfbs->base.base.height = mode_cmd->height; + vfbs->base.pin = &vmw_surface_dmabuf_pin; + vfbs->base.unpin = &vmw_surface_dmabuf_unpin; vfbs->surface = surface; - vfbs->base.user_handle = mode_cmd->handle; vfbs->master = drm_master_get(file_priv->master); + mutex_init(&vfbs->work_lock); mutex_lock(&vmaster->fb_surf_mutex); + INIT_DELAYED_WORK(&vfbs->d_work, &vmw_framebuffer_present_fs_callback); list_add_tail(&vfbs->head, &vmaster->fb_surf); mutex_unlock(&vmaster->fb_surf_mutex); @@ -635,34 +644,48 @@ void vmw_framebuffer_dmabuf_destroy(struct drm_framebuffer *framebuffer) drm_framebuffer_cleanup(framebuffer); vmw_dmabuf_unreference(&vfbd->buffer); - ttm_base_object_unref(&vfbd->base.user_obj); kfree(vfbd); } -static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer, - struct vmw_dma_buffer *buffer, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips, int increment) +int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, + struct drm_file *file_priv, + unsigned flags, unsigned color, + struct drm_clip_rect *clips, + unsigned num_clips) { - size_t fifo_size; - int i; - + struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct drm_clip_rect norect; + int ret; struct { uint32_t header; SVGAFifoCmdUpdate body; } *cmd; + int i, increment = 1; - fifo_size = sizeof(*cmd) * num_clips; - cmd = vmw_fifo_reserve(dev_priv, fifo_size); + ret = ttm_read_lock(&vmaster->lock, true); + if (unlikely(ret != 0)) + return ret; + + if (!num_clips) { + num_clips = 1; + clips = &norect; + norect.x1 = norect.y1 = 0; + norect.x2 = framebuffer->width; + norect.y2 = framebuffer->height; + } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) { + num_clips /= 2; + increment = 2; + } + + cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd) * num_clips); if (unlikely(cmd == NULL)) { DRM_ERROR("Fifo reserve failed.\n"); + ttm_read_unlock(&vmaster->lock); return -ENOMEM; } - memset(cmd, 0, fifo_size); for (i = 0; i < num_clips; i++, clips += increment) { cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE); cmd[i].body.x = cpu_to_le32(clips->x1); @@ -671,180 +694,57 @@ static int do_dmabuf_dirty_ldu(struct vmw_private *dev_priv, cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1); } - vmw_fifo_commit(dev_priv, fifo_size); + vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); + ttm_read_unlock(&vmaster->lock); + return 0; } -static int do_dmabuf_define_gmrfb(struct drm_file *file_priv, - struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer) +static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = { + .destroy = vmw_framebuffer_dmabuf_destroy, + .dirty = vmw_framebuffer_dmabuf_dirty, + .create_handle = vmw_framebuffer_create_handle, +}; + +static int vmw_surface_dmabuf_pin(struct vmw_framebuffer *vfb) { - size_t fifo_size; + struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); + struct vmw_framebuffer_surface *vfbs = + vmw_framebuffer_to_vfbs(&vfb->base); + unsigned long size = vfbs->base.base.pitch * vfbs->base.base.height; int ret; - struct { - uint32_t header; - SVGAFifoCmdDefineGMRFB body; - } *cmd; - - fifo_size = sizeof(*cmd); - cmd = kmalloc(fifo_size, GFP_KERNEL); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed to allocate temporary cmd buffer.\n"); + vfbs->buffer = kzalloc(sizeof(*vfbs->buffer), GFP_KERNEL); + if (unlikely(vfbs->buffer == NULL)) return -ENOMEM; - } - memset(cmd, 0, fifo_size); - cmd->header = SVGA_CMD_DEFINE_GMRFB; - cmd->body.format.bitsPerPixel = framebuffer->base.bits_per_pixel; - cmd->body.format.colorDepth = framebuffer->base.depth; - cmd->body.format.reserved = 0; - cmd->body.bytesPerLine = framebuffer->base.pitch; - cmd->body.ptr.gmrId = framebuffer->user_handle; - cmd->body.ptr.offset = 0; - - ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); - - kfree(cmd); - - return ret; -} - -static int do_dmabuf_dirty_sou(struct drm_file *file_priv, - struct vmw_private *dev_priv, - struct vmw_framebuffer *framebuffer, - struct vmw_dma_buffer *buffer, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips, int increment) -{ - struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; - struct drm_clip_rect *clips_ptr; - int i, k, num_units, ret; - struct drm_crtc *crtc; - size_t fifo_size; - - struct { - uint32_t header; - SVGAFifoCmdBlitGMRFBToScreen body; - } *blits; - - ret = do_dmabuf_define_gmrfb(file_priv, dev_priv, framebuffer); + vmw_overlay_pause_all(dev_priv); + ret = vmw_dmabuf_init(dev_priv, vfbs->buffer, size, + &vmw_vram_ne_placement, + false, &vmw_dmabuf_bo_free); + vmw_overlay_resume_all(dev_priv); if (unlikely(ret != 0)) - return ret; /* define_gmrfb prints warnings */ - - fifo_size = sizeof(*blits) * num_clips; - blits = kmalloc(fifo_size, GFP_KERNEL); - if (unlikely(blits == NULL)) { - DRM_ERROR("Failed to allocate temporary cmd buffer.\n"); - return -ENOMEM; - } - - num_units = 0; - list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { - if (crtc->fb != &framebuffer->base) - continue; - units[num_units++] = vmw_crtc_to_du(crtc); - } - - for (k = 0; k < num_units; k++) { - struct vmw_display_unit *unit = units[k]; - int hit_num = 0; - - clips_ptr = clips; - for (i = 0; i < num_clips; i++, clips_ptr += increment) { - int clip_x1 = clips_ptr->x1 - unit->crtc.x; - int clip_y1 = clips_ptr->y1 - unit->crtc.y; - int clip_x2 = clips_ptr->x2 - unit->crtc.x; - int clip_y2 = clips_ptr->y2 - unit->crtc.y; - - /* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) - continue; - - blits[hit_num].header = SVGA_CMD_BLIT_GMRFB_TO_SCREEN; - blits[hit_num].body.destScreenId = unit->unit; - blits[hit_num].body.srcOrigin.x = clips_ptr->x1; - blits[hit_num].body.srcOrigin.y = clips_ptr->y1; - blits[hit_num].body.destRect.left = clip_x1; - blits[hit_num].body.destRect.top = clip_y1; - blits[hit_num].body.destRect.right = clip_x2; - blits[hit_num].body.destRect.bottom = clip_y2; - hit_num++; - } - - /* no clips hit the crtc */ - if (hit_num == 0) - continue; - - fifo_size = sizeof(*blits) * hit_num; - ret = vmw_execbuf_process(file_priv, dev_priv, NULL, blits, - fifo_size, 0, NULL); - - if (unlikely(ret != 0)) - break; - } - - kfree(blits); + vfbs->buffer = NULL; return ret; } -int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, - struct drm_file *file_priv, - unsigned flags, unsigned color, - struct drm_clip_rect *clips, - unsigned num_clips) +static int vmw_surface_dmabuf_unpin(struct vmw_framebuffer *vfb) { - struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); - struct vmw_master *vmaster = vmw_master(file_priv->master); - struct vmw_framebuffer_dmabuf *vfbd = - vmw_framebuffer_to_vfbd(framebuffer); - struct vmw_dma_buffer *dmabuf = vfbd->buffer; - struct drm_clip_rect norect; - int ret, increment = 1; - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - return ret; + struct ttm_buffer_object *bo; + struct vmw_framebuffer_surface *vfbs = + vmw_framebuffer_to_vfbs(&vfb->base); - if (!num_clips) { - num_clips = 1; - clips = &norect; - norect.x1 = norect.y1 = 0; - norect.x2 = framebuffer->width; - norect.y2 = framebuffer->height; - } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) { - num_clips /= 2; - increment = 2; - } + if (unlikely(vfbs->buffer == NULL)) + return 0; - if (dev_priv->ldu_priv) { - ret = do_dmabuf_dirty_ldu(dev_priv, &vfbd->base, dmabuf, - flags, color, - clips, num_clips, increment); - } else { - ret = do_dmabuf_dirty_sou(file_priv, dev_priv, &vfbd->base, - dmabuf, flags, color, - clips, num_clips, increment); - } + bo = &vfbs->buffer->base; + ttm_bo_unref(&bo); + vfbs->buffer = NULL; - ttm_read_unlock(&vmaster->lock); - return ret; + return 0; } -static struct drm_framebuffer_funcs vmw_framebuffer_dmabuf_funcs = { - .destroy = vmw_framebuffer_dmabuf_destroy, - .dirty = vmw_framebuffer_dmabuf_dirty, - .create_handle = vmw_framebuffer_create_handle, -}; - -/** - * Pin the dmabuffer to the start of vram. - */ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) { struct vmw_private *dev_priv = vmw_priv(vfb->base.dev); @@ -852,12 +752,10 @@ static int vmw_framebuffer_dmabuf_pin(struct vmw_framebuffer *vfb) vmw_framebuffer_to_vfbd(&vfb->base); int ret; - /* This code should not be used with screen objects */ - BUG_ON(dev_priv->sou_priv); vmw_overlay_pause_all(dev_priv); - ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer, true, false); + ret = vmw_dmabuf_to_start_of_vram(dev_priv, vfbd->buffer); vmw_overlay_resume_all(dev_priv); @@ -877,7 +775,7 @@ static int vmw_framebuffer_dmabuf_unpin(struct vmw_framebuffer *vfb) return 0; } - return vmw_dmabuf_unpin(dev_priv, vfbd->buffer, false); + return vmw_dmabuf_from_vram(dev_priv, vfbd->buffer); } static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, @@ -899,33 +797,6 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, return -EINVAL; } - /* Limited framebuffer color depth support for screen objects */ - if (dev_priv->sou_priv) { - switch (mode_cmd->depth) { - case 32: - case 24: - /* Only support 32 bpp for 32 and 24 depth fbs */ - if (mode_cmd->bpp == 32) - break; - - DRM_ERROR("Invalid color depth/bbp: %d %d\n", - mode_cmd->depth, mode_cmd->bpp); - return -EINVAL; - case 16: - case 15: - /* Only support 16 bpp for 16 and 15 depth fbs */ - if (mode_cmd->bpp == 16) - break; - - DRM_ERROR("Invalid color depth/bbp: %d %d\n", - mode_cmd->depth, mode_cmd->bpp); - return -EINVAL; - default: - DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth); - return -EINVAL; - } - } - vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL); if (!vfbd) { ret = -ENOMEM; @@ -947,13 +818,9 @@ static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv, vfbd->base.base.depth = mode_cmd->depth; vfbd->base.base.width = mode_cmd->width; vfbd->base.base.height = mode_cmd->height; - if (!dev_priv->sou_priv) { - vfbd->base.pin = vmw_framebuffer_dmabuf_pin; - vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin; - } - vfbd->base.dmabuf = true; + vfbd->base.pin = vmw_framebuffer_dmabuf_pin; + vfbd->base.unpin = vmw_framebuffer_dmabuf_unpin; vfbd->buffer = dmabuf; - vfbd->base.user_handle = mode_cmd->handle; *out = &vfbd->base; return 0; @@ -979,7 +846,6 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct vmw_framebuffer *vfb = NULL; struct vmw_surface *surface = NULL; struct vmw_dma_buffer *bo = NULL; - struct ttm_base_object *user_obj; u64 required_size; int ret; @@ -995,21 +861,6 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, return NULL; } - /* - * Take a reference on the user object of the resource - * backing the kms fb. This ensures that user-space handle - * lookups on that resource will always work as long as - * it's registered with a kms framebuffer. This is important, - * since vmw_execbuf_process identifies resources in the - * command stream using user-space handles. - */ - - user_obj = ttm_base_object_lookup(tfile, mode_cmd->handle); - if (unlikely(user_obj == NULL)) { - DRM_ERROR("Could not locate requested kms frame buffer.\n"); - return ERR_PTR(-ENOENT); - } - /** * End conditioned code. */ @@ -1030,10 +881,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, if (ret) { DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); - ttm_base_object_unref(&user_obj); return ERR_PTR(ret); - } else - vfb->user_obj = user_obj; + } return &vfb->base; try_dmabuf: @@ -1053,10 +902,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, if (ret) { DRM_ERROR("failed to create vmw_framebuffer: %i\n", ret); - ttm_base_object_unref(&user_obj); return ERR_PTR(ret); - } else - vfb->user_obj = user_obj; + } return &vfb->base; @@ -1064,7 +911,6 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, DRM_ERROR("surface not marked as scanout\n"); /* vmw_user_surface_lookup takes one ref */ vmw_surface_unreference(&surface); - ttm_base_object_unref(&user_obj); return ERR_PTR(-EINVAL); } @@ -1073,210 +919,6 @@ static struct drm_mode_config_funcs vmw_kms_funcs = { .fb_create = vmw_kms_fb_create, }; -int vmw_kms_present(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct vmw_surface *surface, - uint32_t sid, - int32_t destX, int32_t destY, - struct drm_vmw_rect *clips, - uint32_t num_clips) -{ - struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; - struct drm_crtc *crtc; - size_t fifo_size; - int i, k, num_units; - int ret = 0; /* silence warning */ - - struct { - SVGA3dCmdHeader header; - SVGA3dCmdBlitSurfaceToScreen body; - } *cmd; - SVGASignedRect *blits; - - num_units = 0; - list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { - if (crtc->fb != &vfb->base) - continue; - units[num_units++] = vmw_crtc_to_du(crtc); - } - - BUG_ON(surface == NULL); - BUG_ON(!clips || !num_clips); - - fifo_size = sizeof(*cmd) + sizeof(SVGASignedRect) * num_clips; - cmd = kmalloc(fifo_size, GFP_KERNEL); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed to allocate temporary fifo memory.\n"); - return -ENOMEM; - } - - /* only need to do this once */ - memset(cmd, 0, fifo_size); - cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN); - cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header)); - - cmd->body.srcRect.left = 0; - cmd->body.srcRect.right = surface->sizes[0].width; - cmd->body.srcRect.top = 0; - cmd->body.srcRect.bottom = surface->sizes[0].height; - - blits = (SVGASignedRect *)&cmd[1]; - for (i = 0; i < num_clips; i++) { - blits[i].left = clips[i].x; - blits[i].right = clips[i].x + clips[i].w; - blits[i].top = clips[i].y; - blits[i].bottom = clips[i].y + clips[i].h; - } - - for (k = 0; k < num_units; k++) { - struct vmw_display_unit *unit = units[k]; - int clip_x1 = destX - unit->crtc.x; - int clip_y1 = destY - unit->crtc.y; - int clip_x2 = clip_x1 + surface->sizes[0].width; - int clip_y2 = clip_y1 + surface->sizes[0].height; - - /* skip any crtcs that misses the clip region */ - if (clip_x1 >= unit->crtc.mode.hdisplay || - clip_y1 >= unit->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) - continue; - - /* need to reset sid as it is changed by execbuf */ - cmd->body.srcImage.sid = sid; - - cmd->body.destScreenId = unit->unit; - - /* - * The blit command is a lot more resilient then the - * readback command when it comes to clip rects. So its - * okay to go out of bounds. - */ - - cmd->body.destRect.left = clip_x1; - cmd->body.destRect.right = clip_x2; - cmd->body.destRect.top = clip_y1; - cmd->body.destRect.bottom = clip_y2; - - ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, - fifo_size, 0, NULL); - - if (unlikely(ret != 0)) - break; - } - - kfree(cmd); - - return ret; -} - -int vmw_kms_readback(struct vmw_private *dev_priv, - struct drm_file *file_priv, - struct vmw_framebuffer *vfb, - struct drm_vmw_fence_rep __user *user_fence_rep, - struct drm_vmw_rect *clips, - uint32_t num_clips) -{ - struct vmw_framebuffer_dmabuf *vfbd = - vmw_framebuffer_to_vfbd(&vfb->base); - struct vmw_dma_buffer *dmabuf = vfbd->buffer; - struct vmw_display_unit *units[VMWGFX_NUM_DISPLAY_UNITS]; - struct drm_crtc *crtc; - size_t fifo_size; - int i, k, ret, num_units, blits_pos; - - struct { - uint32_t header; - SVGAFifoCmdDefineGMRFB body; - } *cmd; - struct { - uint32_t header; - SVGAFifoCmdBlitScreenToGMRFB body; - } *blits; - - num_units = 0; - list_for_each_entry(crtc, &dev_priv->dev->mode_config.crtc_list, head) { - if (crtc->fb != &vfb->base) - continue; - units[num_units++] = vmw_crtc_to_du(crtc); - } - - BUG_ON(dmabuf == NULL); - BUG_ON(!clips || !num_clips); - - /* take a safe guess at fifo size */ - fifo_size = sizeof(*cmd) + sizeof(*blits) * num_clips * num_units; - cmd = kmalloc(fifo_size, GFP_KERNEL); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed to allocate temporary fifo memory.\n"); - return -ENOMEM; - } - - memset(cmd, 0, fifo_size); - cmd->header = SVGA_CMD_DEFINE_GMRFB; - cmd->body.format.bitsPerPixel = vfb->base.bits_per_pixel; - cmd->body.format.colorDepth = vfb->base.depth; - cmd->body.format.reserved = 0; - cmd->body.bytesPerLine = vfb->base.pitch; - cmd->body.ptr.gmrId = vfb->user_handle; - cmd->body.ptr.offset = 0; - - blits = (void *)&cmd[1]; - blits_pos = 0; - for (i = 0; i < num_units; i++) { - struct drm_vmw_rect *c = clips; - for (k = 0; k < num_clips; k++, c++) { - /* transform clip coords to crtc origin based coords */ - int clip_x1 = c->x - units[i]->crtc.x; - int clip_x2 = c->x - units[i]->crtc.x + c->w; - int clip_y1 = c->y - units[i]->crtc.y; - int clip_y2 = c->y - units[i]->crtc.y + c->h; - int dest_x = c->x; - int dest_y = c->y; - - /* compensate for clipping, we negate - * a negative number and add that. - */ - if (clip_x1 < 0) - dest_x += -clip_x1; - if (clip_y1 < 0) - dest_y += -clip_y1; - - /* clip */ - clip_x1 = max(clip_x1, 0); - clip_y1 = max(clip_y1, 0); - clip_x2 = min(clip_x2, units[i]->crtc.mode.hdisplay); - clip_y2 = min(clip_y2, units[i]->crtc.mode.vdisplay); - - /* and cull any rects that misses the crtc */ - if (clip_x1 >= units[i]->crtc.mode.hdisplay || - clip_y1 >= units[i]->crtc.mode.vdisplay || - clip_x2 <= 0 || clip_y2 <= 0) - continue; - - blits[blits_pos].header = SVGA_CMD_BLIT_SCREEN_TO_GMRFB; - blits[blits_pos].body.srcScreenId = units[i]->unit; - blits[blits_pos].body.destOrigin.x = dest_x; - blits[blits_pos].body.destOrigin.y = dest_y; - - blits[blits_pos].body.srcRect.left = clip_x1; - blits[blits_pos].body.srcRect.top = clip_y1; - blits[blits_pos].body.srcRect.right = clip_x2; - blits[blits_pos].body.srcRect.bottom = clip_y2; - blits_pos++; - } - } - /* reset size here and use calculated exact size from loops */ - fifo_size = sizeof(*cmd) + sizeof(*blits) * blits_pos; - - ret = vmw_execbuf_process(file_priv, dev_priv, NULL, cmd, fifo_size, - 0, user_fence_rep); - - kfree(cmd); - - return ret; -} - int vmw_kms_init(struct vmw_private *dev_priv) { struct drm_device *dev = dev_priv->dev; @@ -1290,9 +932,7 @@ int vmw_kms_init(struct vmw_private *dev_priv) dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; - ret = vmw_kms_init_screen_object_display(dev_priv); - if (ret) /* Fallback */ - (void)vmw_kms_init_legacy_display_system(dev_priv); + ret = vmw_kms_init_legacy_display_system(dev_priv); return 0; } @@ -1463,242 +1103,3 @@ u32 vmw_get_vblank_counter(struct drm_device *dev, int crtc) { return 0; } - - -/* - * Small shared kms functions. - */ - -int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, - struct drm_vmw_rect *rects) -{ - struct drm_device *dev = dev_priv->dev; - struct vmw_display_unit *du; - struct drm_connector *con; - - mutex_lock(&dev->mode_config.mutex); - -#if 0 - { - unsigned int i; - - DRM_INFO("%s: new layout ", __func__); - for (i = 0; i < num; i++) - DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y, - rects[i].w, rects[i].h); - DRM_INFO("\n"); - } -#endif - - list_for_each_entry(con, &dev->mode_config.connector_list, head) { - du = vmw_connector_to_du(con); - if (num > du->unit) { - du->pref_width = rects[du->unit].w; - du->pref_height = rects[du->unit].h; - du->pref_active = true; - } else { - du->pref_width = 800; - du->pref_height = 600; - du->pref_active = false; - } - con->status = vmw_du_connector_detect(con, true); - } - - mutex_unlock(&dev->mode_config.mutex); - - return 0; -} - -void vmw_du_crtc_save(struct drm_crtc *crtc) -{ -} - -void vmw_du_crtc_restore(struct drm_crtc *crtc) -{ -} - -void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, - u16 *r, u16 *g, u16 *b, - uint32_t start, uint32_t size) -{ - struct vmw_private *dev_priv = vmw_priv(crtc->dev); - int i; - - for (i = 0; i < size; i++) { - DRM_DEBUG("%d r/g/b = 0x%04x / 0x%04x / 0x%04x\n", i, - r[i], g[i], b[i]); - vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 0, r[i] >> 8); - vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 1, g[i] >> 8); - vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 2, b[i] >> 8); - } -} - -void vmw_du_connector_dpms(struct drm_connector *connector, int mode) -{ -} - -void vmw_du_connector_save(struct drm_connector *connector) -{ -} - -void vmw_du_connector_restore(struct drm_connector *connector) -{ -} - -enum drm_connector_status -vmw_du_connector_detect(struct drm_connector *connector, bool force) -{ - uint32_t num_displays; - struct drm_device *dev = connector->dev; - struct vmw_private *dev_priv = vmw_priv(dev); - - mutex_lock(&dev_priv->hw_mutex); - num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); - mutex_unlock(&dev_priv->hw_mutex); - - return ((vmw_connector_to_du(connector)->unit < num_displays) ? - connector_status_connected : connector_status_disconnected); -} - -static struct drm_display_mode vmw_kms_connector_builtin[] = { - /* 640x480@60Hz */ - { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, - 752, 800, 0, 480, 489, 492, 525, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 800x600@60Hz */ - { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, - 968, 1056, 0, 600, 601, 605, 628, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1024x768@60Hz */ - { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, - 1184, 1344, 0, 768, 771, 777, 806, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 1152x864@75Hz */ - { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, - 1344, 1600, 0, 864, 865, 868, 900, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1280x768@60Hz */ - { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, - 1472, 1664, 0, 768, 771, 778, 798, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1280x800@60Hz */ - { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, - 1480, 1680, 0, 800, 803, 809, 831, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, - /* 1280x960@60Hz */ - { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, - 1488, 1800, 0, 960, 961, 964, 1000, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1280x1024@60Hz */ - { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, - 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1360x768@60Hz */ - { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, - 1536, 1792, 0, 768, 771, 777, 795, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1440x1050@60Hz */ - { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, - 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1440x900@60Hz */ - { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, - 1672, 1904, 0, 900, 903, 909, 934, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1600x1200@60Hz */ - { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, - 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, - DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1680x1050@60Hz */ - { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, - 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1792x1344@60Hz */ - { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, - 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1853x1392@60Hz */ - { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, - 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1920x1200@60Hz */ - { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, - 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 1920x1440@60Hz */ - { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, - 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* 2560x1600@60Hz */ - { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, - 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, - /* Terminate */ - { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }, -}; - -int vmw_du_connector_fill_modes(struct drm_connector *connector, - uint32_t max_width, uint32_t max_height) -{ - struct vmw_display_unit *du = vmw_connector_to_du(connector); - struct drm_device *dev = connector->dev; - struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_display_mode *mode = NULL; - struct drm_display_mode *bmode; - struct drm_display_mode prefmode = { DRM_MODE("preferred", - DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) - }; - int i; - - /* Add preferred mode */ - { - mode = drm_mode_duplicate(dev, &prefmode); - if (!mode) - return 0; - mode->hdisplay = du->pref_width; - mode->vdisplay = du->pref_height; - mode->vrefresh = drm_mode_vrefresh(mode); - if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, - mode->vdisplay)) { - drm_mode_probed_add(connector, mode); - - if (du->pref_mode) { - list_del_init(&du->pref_mode->head); - drm_mode_destroy(dev, du->pref_mode); - } - - du->pref_mode = mode; - } - } - - for (i = 0; vmw_kms_connector_builtin[i].type != 0; i++) { - bmode = &vmw_kms_connector_builtin[i]; - if (bmode->hdisplay > max_width || - bmode->vdisplay > max_height) - continue; - - if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, - bmode->vdisplay)) - continue; - - mode = drm_mode_duplicate(dev, bmode); - if (!mode) - return 0; - mode->vrefresh = drm_mode_vrefresh(mode); - - drm_mode_probed_add(connector, mode); - } - - drm_mode_connector_list_update(connector); - - return 1; -} - -int vmw_du_connector_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - return 0; -} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index db0b901f8c3f..8a398a0339b6 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -31,8 +31,6 @@ #include "drmP.h" #include "vmwgfx_drv.h" -#define VMWGFX_NUM_DISPLAY_UNITS 8 - #define vmw_framebuffer_to_vfb(x) \ container_of(x, struct vmw_framebuffer, base) @@ -47,9 +45,6 @@ struct vmw_framebuffer { struct drm_framebuffer base; int (*pin)(struct vmw_framebuffer *fb); int (*unpin)(struct vmw_framebuffer *fb); - bool dmabuf; - struct ttm_base_object *user_obj; - uint32_t user_handle; }; @@ -88,59 +83,22 @@ struct vmw_display_unit { int hotspot_y; unsigned unit; - - /* - * Prefered mode tracking. - */ - unsigned pref_width; - unsigned pref_height; - bool pref_active; - struct drm_display_mode *pref_mode; }; -#define vmw_crtc_to_du(x) \ - container_of(x, struct vmw_display_unit, crtc) -#define vmw_connector_to_du(x) \ - container_of(x, struct vmw_display_unit, connector) - - /* * Shared display unit functions - vmwgfx_kms.c */ void vmw_display_unit_cleanup(struct vmw_display_unit *du); -void vmw_du_crtc_save(struct drm_crtc *crtc); -void vmw_du_crtc_restore(struct drm_crtc *crtc); -void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, - u16 *r, u16 *g, u16 *b, - uint32_t start, uint32_t size); int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, uint32_t width, uint32_t height); int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); -void vmw_du_connector_dpms(struct drm_connector *connector, int mode); -void vmw_du_connector_save(struct drm_connector *connector); -void vmw_du_connector_restore(struct drm_connector *connector); -enum drm_connector_status -vmw_du_connector_detect(struct drm_connector *connector, bool force); -int vmw_du_connector_fill_modes(struct drm_connector *connector, - uint32_t max_width, uint32_t max_height); -int vmw_du_connector_set_property(struct drm_connector *connector, - struct drm_property *property, - uint64_t val); -int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num, - struct drm_vmw_rect *rects); /* * Legacy display unit functions - vmwgfx_ldu.c */ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv); int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv); - -/* - * Screen Objects display functions - vmwgfx_scrn.c - */ -int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv); -int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv); -int vmw_kms_sou_update_layout(struct vmw_private *dev_priv, unsigned num, +int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, struct drm_vmw_rect *rects); #endif diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 7fc8e7de180b..7e1901c4f065 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -27,6 +27,7 @@ #include "vmwgfx_kms.h" +#define VMWGFX_LDU_NUM_DU 8 #define vmw_crtc_to_ldu(x) \ container_of(x, struct vmw_legacy_display_unit, base.crtc) @@ -50,6 +51,11 @@ struct vmw_legacy_display { struct vmw_legacy_display_unit { struct vmw_display_unit base; + unsigned pref_width; + unsigned pref_height; + bool pref_active; + struct drm_display_mode *pref_mode; + struct list_head active; }; @@ -65,6 +71,29 @@ static void vmw_ldu_destroy(struct vmw_legacy_display_unit *ldu) * Legacy Display Unit CRTC functions */ +static void vmw_ldu_crtc_save(struct drm_crtc *crtc) +{ +} + +static void vmw_ldu_crtc_restore(struct drm_crtc *crtc) +{ +} + +static void vmw_ldu_crtc_gamma_set(struct drm_crtc *crtc, + u16 *r, u16 *g, u16 *b, + uint32_t start, uint32_t size) +{ + struct vmw_private *dev_priv = vmw_priv(crtc->dev); + int i; + + for (i = 0; i < size; i++) { + DRM_DEBUG("%d r/g/b = 0x%04x / 0x%04x / 0x%04x\n", i, r[i], g[i], b[i]); + vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 0, r[i] >> 8); + vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 1, g[i] >> 8); + vmw_write(dev_priv, SVGA_PALETTE_BASE + i * 3 + 2, b[i] >> 8); + } +} + static void vmw_ldu_crtc_destroy(struct drm_crtc *crtc) { vmw_ldu_destroy(vmw_crtc_to_ldu(crtc)); @@ -272,16 +301,15 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) } static struct drm_crtc_funcs vmw_legacy_crtc_funcs = { - .save = vmw_du_crtc_save, - .restore = vmw_du_crtc_restore, + .save = vmw_ldu_crtc_save, + .restore = vmw_ldu_crtc_restore, .cursor_set = vmw_du_crtc_cursor_set, .cursor_move = vmw_du_crtc_cursor_move, - .gamma_set = vmw_du_crtc_gamma_set, + .gamma_set = vmw_ldu_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, .set_config = vmw_ldu_crtc_set_config, }; - /* * Legacy Display Unit encoder functions */ @@ -299,18 +327,190 @@ static struct drm_encoder_funcs vmw_legacy_encoder_funcs = { * Legacy Display Unit connector functions */ +static void vmw_ldu_connector_dpms(struct drm_connector *connector, int mode) +{ +} + +static void vmw_ldu_connector_save(struct drm_connector *connector) +{ +} + +static void vmw_ldu_connector_restore(struct drm_connector *connector) +{ +} + +static enum drm_connector_status + vmw_ldu_connector_detect(struct drm_connector *connector, + bool force) +{ + uint32_t num_displays; + struct drm_device *dev = connector->dev; + struct vmw_private *dev_priv = vmw_priv(dev); + + mutex_lock(&dev_priv->hw_mutex); + num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); + mutex_unlock(&dev_priv->hw_mutex); + + return ((vmw_connector_to_ldu(connector)->base.unit < num_displays) ? + connector_status_connected : connector_status_disconnected); +} + +static const struct drm_display_mode vmw_ldu_connector_builtin[] = { + /* 640x480@60Hz */ + { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, + 752, 800, 0, 480, 489, 492, 525, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 800x600@60Hz */ + { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, + 968, 1056, 0, 600, 601, 605, 628, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1024x768@60Hz */ + { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, + 1184, 1344, 0, 768, 771, 777, 806, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1152x864@75Hz */ + { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, + 1344, 1600, 0, 864, 865, 868, 900, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1280x768@60Hz */ + { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, + 1472, 1664, 0, 768, 771, 778, 798, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1280x800@60Hz */ + { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, + 1480, 1680, 0, 800, 803, 809, 831, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, + /* 1280x960@60Hz */ + { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, + 1488, 1800, 0, 960, 961, 964, 1000, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1280x1024@60Hz */ + { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, + 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1360x768@60Hz */ + { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, + 1536, 1792, 0, 768, 771, 777, 795, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1440x1050@60Hz */ + { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, + 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1440x900@60Hz */ + { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, + 1672, 1904, 0, 900, 903, 909, 934, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1600x1200@60Hz */ + { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, + 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, + DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1680x1050@60Hz */ + { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, + 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1792x1344@60Hz */ + { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, + 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1853x1392@60Hz */ + { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, + 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1920x1200@60Hz */ + { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, + 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 1920x1440@60Hz */ + { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, + 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* 2560x1600@60Hz */ + { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, + 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, + /* Terminate */ + { DRM_MODE("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) }, +}; + +static int vmw_ldu_connector_fill_modes(struct drm_connector *connector, + uint32_t max_width, uint32_t max_height) +{ + struct vmw_legacy_display_unit *ldu = vmw_connector_to_ldu(connector); + struct drm_device *dev = connector->dev; + struct vmw_private *dev_priv = vmw_priv(dev); + struct drm_display_mode *mode = NULL; + struct drm_display_mode prefmode = { DRM_MODE("preferred", + DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) + }; + int i; + + /* Add preferred mode */ + { + mode = drm_mode_duplicate(dev, &prefmode); + if (!mode) + return 0; + mode->hdisplay = ldu->pref_width; + mode->vdisplay = ldu->pref_height; + mode->vrefresh = drm_mode_vrefresh(mode); + if (vmw_kms_validate_mode_vram(dev_priv, mode->hdisplay * 2, + mode->vdisplay)) { + drm_mode_probed_add(connector, mode); + + if (ldu->pref_mode) { + list_del_init(&ldu->pref_mode->head); + drm_mode_destroy(dev, ldu->pref_mode); + } + + ldu->pref_mode = mode; + } + } + + for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) { + const struct drm_display_mode *bmode; + + bmode = &vmw_ldu_connector_builtin[i]; + if (bmode->hdisplay > max_width || + bmode->vdisplay > max_height) + continue; + + if (!vmw_kms_validate_mode_vram(dev_priv, bmode->hdisplay * 2, + bmode->vdisplay)) + continue; + + mode = drm_mode_duplicate(dev, bmode); + if (!mode) + return 0; + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_probed_add(connector, mode); + } + + drm_mode_connector_list_update(connector); + + return 1; +} + +static int vmw_ldu_connector_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + return 0; +} + static void vmw_ldu_connector_destroy(struct drm_connector *connector) { vmw_ldu_destroy(vmw_connector_to_ldu(connector)); } static struct drm_connector_funcs vmw_legacy_connector_funcs = { - .dpms = vmw_du_connector_dpms, - .save = vmw_du_connector_save, - .restore = vmw_du_connector_restore, - .detect = vmw_du_connector_detect, - .fill_modes = vmw_du_connector_fill_modes, - .set_property = vmw_du_connector_set_property, + .dpms = vmw_ldu_connector_dpms, + .save = vmw_ldu_connector_save, + .restore = vmw_ldu_connector_restore, + .detect = vmw_ldu_connector_detect, + .fill_modes = vmw_ldu_connector_fill_modes, + .set_property = vmw_ldu_connector_set_property, .destroy = vmw_ldu_connector_destroy, }; @@ -333,14 +533,14 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) INIT_LIST_HEAD(&ldu->active); - ldu->base.pref_active = (unit == 0); - ldu->base.pref_width = 800; - ldu->base.pref_height = 600; - ldu->base.pref_mode = NULL; + ldu->pref_active = (unit == 0); + ldu->pref_width = 800; + ldu->pref_height = 600; + ldu->pref_mode = NULL; drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, DRM_MODE_CONNECTOR_LVDS); - connector->status = vmw_du_connector_detect(connector, true); + connector->status = vmw_ldu_connector_detect(connector, true); drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs, DRM_MODE_ENCODER_LVDS); @@ -383,9 +583,9 @@ int vmw_kms_init_legacy_display_system(struct vmw_private *dev_priv) drm_mode_create_dirty_info_property(dev_priv->dev); if (dev_priv->capabilities & SVGA_CAP_MULTIMON) { - for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) + for (i = 0; i < VMWGFX_LDU_NUM_DU; ++i) vmw_ldu_init(dev_priv, i); - ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); + ret = drm_vblank_init(dev, VMWGFX_LDU_NUM_DU); } else { /* for old hardware without multimon only enable one display */ vmw_ldu_init(dev_priv, 0); @@ -409,3 +609,42 @@ int vmw_kms_close_legacy_display_system(struct vmw_private *dev_priv) return 0; } + +int vmw_kms_ldu_update_layout(struct vmw_private *dev_priv, unsigned num, + struct drm_vmw_rect *rects) +{ + struct drm_device *dev = dev_priv->dev; + struct vmw_legacy_display_unit *ldu; + struct drm_connector *con; + int i; + + mutex_lock(&dev->mode_config.mutex); + +#if 0 + DRM_INFO("%s: new layout ", __func__); + for (i = 0; i < (int)num; i++) + DRM_INFO("(%i, %i %ux%u) ", rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + DRM_INFO("\n"); +#else + (void)i; +#endif + + list_for_each_entry(con, &dev->mode_config.connector_list, head) { + ldu = vmw_connector_to_ldu(con); + if (num > ldu->base.unit) { + ldu->pref_width = rects[ldu->base.unit].w; + ldu->pref_height = rects[ldu->base.unit].h; + ldu->pref_active = true; + } else { + ldu->pref_width = 800; + ldu->pref_height = 600; + ldu->pref_active = false; + } + con->status = vmw_ldu_connector_detect(con, true); + } + + mutex_unlock(&dev->mode_config.mutex); + + return 0; +} diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index 14399eec9c3c..07ce02da78a4 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -86,6 +86,48 @@ static inline void fill_flush(struct vmw_escape_video_flush *cmd, cmd->flush.streamId = stream_id; } +/** + * Pin or unpin a buffer in vram. + * + * @dev_priv: Driver private. + * @buf: DMA buffer to pin or unpin. + * @pin: Pin buffer in vram if true. + * @interruptible: Use interruptible wait. + * + * Takes the current masters ttm lock in read. + * + * Returns + * -ERESTARTSYS if interrupted by a signal. + */ +static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, + struct vmw_dma_buffer *buf, + bool pin, bool interruptible) +{ + struct ttm_buffer_object *bo = &buf->base; + struct ttm_placement *overlay_placement = &vmw_vram_placement; + int ret; + + ret = ttm_read_lock(&dev_priv->active_master->lock, interruptible); + if (unlikely(ret != 0)) + return ret; + + ret = ttm_bo_reserve(bo, interruptible, false, false, 0); + if (unlikely(ret != 0)) + goto err; + + if (pin) + overlay_placement = &vmw_vram_ne_placement; + + ret = ttm_bo_validate(bo, overlay_placement, interruptible, false, false); + + ttm_bo_unreserve(bo); + +err: + ttm_read_unlock(&dev_priv->active_master->lock); + + return ret; +} + /** * Send put command to hw. * @@ -97,80 +139,68 @@ static int vmw_overlay_send_put(struct vmw_private *dev_priv, struct drm_vmw_control_stream_arg *arg, bool interruptible) { - struct vmw_escape_video_flush *flush; - size_t fifo_size; - bool have_so = dev_priv->sou_priv ? true : false; - int i, num_items; - SVGAGuestPtr ptr; - struct { struct vmw_escape_header escape; struct { - uint32_t cmdType; - uint32_t streamId; - } header; + struct { + uint32_t cmdType; + uint32_t streamId; + } header; + struct { + uint32_t registerId; + uint32_t value; + } items[SVGA_VIDEO_PITCH_3 + 1]; + } body; + struct vmw_escape_video_flush flush; } *cmds; - struct { - uint32_t registerId; - uint32_t value; - } *items; - - /* defines are a index needs + 1 */ - if (have_so) - num_items = SVGA_VIDEO_DST_SCREEN_ID + 1; - else - num_items = SVGA_VIDEO_PITCH_3 + 1; - - fifo_size = sizeof(*cmds) + sizeof(*flush) + sizeof(*items) * num_items; + uint32_t offset; + int i, ret; - cmds = vmw_fifo_reserve(dev_priv, fifo_size); - /* hardware has hung, can't do anything here */ - if (!cmds) - return -ENOMEM; + for (;;) { + cmds = vmw_fifo_reserve(dev_priv, sizeof(*cmds)); + if (cmds) + break; - items = (typeof(items))&cmds[1]; - flush = (struct vmw_escape_video_flush *)&items[num_items]; - - /* the size is header + number of items */ - fill_escape(&cmds->escape, sizeof(*items) * (num_items + 1)); - - cmds->header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; - cmds->header.streamId = arg->stream_id; - - /* the IDs are neatly numbered */ - for (i = 0; i < num_items; i++) - items[i].registerId = i; - - vmw_bo_get_guest_ptr(&buf->base, &ptr); - ptr.offset += arg->offset; - - items[SVGA_VIDEO_ENABLED].value = true; - items[SVGA_VIDEO_FLAGS].value = arg->flags; - items[SVGA_VIDEO_DATA_OFFSET].value = ptr.offset; - items[SVGA_VIDEO_FORMAT].value = arg->format; - items[SVGA_VIDEO_COLORKEY].value = arg->color_key; - items[SVGA_VIDEO_SIZE].value = arg->size; - items[SVGA_VIDEO_WIDTH].value = arg->width; - items[SVGA_VIDEO_HEIGHT].value = arg->height; - items[SVGA_VIDEO_SRC_X].value = arg->src.x; - items[SVGA_VIDEO_SRC_Y].value = arg->src.y; - items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w; - items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h; - items[SVGA_VIDEO_DST_X].value = arg->dst.x; - items[SVGA_VIDEO_DST_Y].value = arg->dst.y; - items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w; - items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h; - items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0]; - items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1]; - items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2]; - if (have_so) { - items[SVGA_VIDEO_DATA_GMRID].value = ptr.gmrId; - items[SVGA_VIDEO_DST_SCREEN_ID].value = SVGA_ID_INVALID; + ret = vmw_fallback_wait(dev_priv, false, true, 0, + interruptible, 3*HZ); + if (interruptible && ret == -ERESTARTSYS) + return ret; + else + BUG_ON(ret != 0); } - fill_flush(flush, arg->stream_id); + fill_escape(&cmds->escape, sizeof(cmds->body)); + cmds->body.header.cmdType = SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS; + cmds->body.header.streamId = arg->stream_id; + + for (i = 0; i <= SVGA_VIDEO_PITCH_3; i++) + cmds->body.items[i].registerId = i; + + offset = buf->base.offset + arg->offset; + + cmds->body.items[SVGA_VIDEO_ENABLED].value = true; + cmds->body.items[SVGA_VIDEO_FLAGS].value = arg->flags; + cmds->body.items[SVGA_VIDEO_DATA_OFFSET].value = offset; + cmds->body.items[SVGA_VIDEO_FORMAT].value = arg->format; + cmds->body.items[SVGA_VIDEO_COLORKEY].value = arg->color_key; + cmds->body.items[SVGA_VIDEO_SIZE].value = arg->size; + cmds->body.items[SVGA_VIDEO_WIDTH].value = arg->width; + cmds->body.items[SVGA_VIDEO_HEIGHT].value = arg->height; + cmds->body.items[SVGA_VIDEO_SRC_X].value = arg->src.x; + cmds->body.items[SVGA_VIDEO_SRC_Y].value = arg->src.y; + cmds->body.items[SVGA_VIDEO_SRC_WIDTH].value = arg->src.w; + cmds->body.items[SVGA_VIDEO_SRC_HEIGHT].value = arg->src.h; + cmds->body.items[SVGA_VIDEO_DST_X].value = arg->dst.x; + cmds->body.items[SVGA_VIDEO_DST_Y].value = arg->dst.y; + cmds->body.items[SVGA_VIDEO_DST_WIDTH].value = arg->dst.w; + cmds->body.items[SVGA_VIDEO_DST_HEIGHT].value = arg->dst.h; + cmds->body.items[SVGA_VIDEO_PITCH_1].value = arg->pitch[0]; + cmds->body.items[SVGA_VIDEO_PITCH_2].value = arg->pitch[1]; + cmds->body.items[SVGA_VIDEO_PITCH_3].value = arg->pitch[2]; + + fill_flush(&cmds->flush, arg->stream_id); - vmw_fifo_commit(dev_priv, fifo_size); + vmw_fifo_commit(dev_priv, sizeof(*cmds)); return 0; } @@ -217,25 +247,6 @@ static int vmw_overlay_send_stop(struct vmw_private *dev_priv, return 0; } -/** - * Move a buffer to vram or gmr if @pin is set, else unpin the buffer. - * - * With the introduction of screen objects buffers could now be - * used with GMRs instead of being locked to vram. - */ -static int vmw_overlay_move_buffer(struct vmw_private *dev_priv, - struct vmw_dma_buffer *buf, - bool pin, bool inter) -{ - if (!pin) - return vmw_dmabuf_unpin(dev_priv, buf, inter); - - if (!dev_priv->sou_priv) - return vmw_dmabuf_to_vram(dev_priv, buf, true, inter); - - return vmw_dmabuf_to_vram_or_gmr(dev_priv, buf, true, inter); -} - /** * Stop or pause a stream. * @@ -268,8 +279,8 @@ static int vmw_overlay_stop(struct vmw_private *dev_priv, return ret; /* We just remove the NO_EVICT flag so no -ENOMEM */ - ret = vmw_overlay_move_buffer(dev_priv, stream->buf, false, - interruptible); + ret = vmw_dmabuf_pin_in_vram(dev_priv, stream->buf, false, + interruptible); if (interruptible && ret == -ERESTARTSYS) return ret; else @@ -331,7 +342,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, /* We don't start the old stream if we are interrupted. * Might return -ENOMEM if it can't fit the buffer in vram. */ - ret = vmw_overlay_move_buffer(dev_priv, buf, true, interruptible); + ret = vmw_dmabuf_pin_in_vram(dev_priv, buf, true, interruptible); if (ret) return ret; @@ -340,8 +351,7 @@ static int vmw_overlay_update_stream(struct vmw_private *dev_priv, /* This one needs to happen no matter what. We only remove * the NO_EVICT flag so this is safe from -ENOMEM. */ - BUG_ON(vmw_overlay_move_buffer(dev_priv, buf, false, false) - != 0); + BUG_ON(vmw_dmabuf_pin_in_vram(dev_priv, buf, false, false) != 0); return ret; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index c7cff3debe11..c1b6ffd4ce7b 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -39,7 +39,6 @@ struct vmw_user_context { struct vmw_user_surface { struct ttm_base_object base; struct vmw_surface srf; - uint32_t size; }; struct vmw_user_dma_buffer { @@ -62,17 +61,6 @@ struct vmw_user_stream { struct vmw_stream stream; }; -struct vmw_surface_offset { - uint32_t face; - uint32_t mip; - uint32_t bo_offset; -}; - - -static uint64_t vmw_user_context_size; -static uint64_t vmw_user_surface_size; -static uint64_t vmw_user_stream_size; - static inline struct vmw_dma_buffer * vmw_dma_buffer(struct ttm_buffer_object *bo) { @@ -92,36 +80,13 @@ struct vmw_resource *vmw_resource_reference(struct vmw_resource *res) return res; } - -/** - * vmw_resource_release_id - release a resource id to the id manager. - * - * @res: Pointer to the resource. - * - * Release the resource id to the resource id manager and set it to -1 - */ -static void vmw_resource_release_id(struct vmw_resource *res) -{ - struct vmw_private *dev_priv = res->dev_priv; - - write_lock(&dev_priv->resource_lock); - if (res->id != -1) - idr_remove(res->idr, res->id); - res->id = -1; - write_unlock(&dev_priv->resource_lock); -} - static void vmw_resource_release(struct kref *kref) { struct vmw_resource *res = container_of(kref, struct vmw_resource, kref); struct vmw_private *dev_priv = res->dev_priv; - int id = res->id; - struct idr *idr = res->idr; - res->avail = false; - if (res->remove_from_lists != NULL) - res->remove_from_lists(res); + idr_remove(res->idr, res->id); write_unlock(&dev_priv->resource_lock); if (likely(res->hw_destroy != NULL)) @@ -133,9 +98,6 @@ static void vmw_resource_release(struct kref *kref) kfree(res); write_lock(&dev_priv->resource_lock); - - if (id != -1) - idr_remove(idr, id); } void vmw_resource_unreference(struct vmw_resource **p_res) @@ -149,29 +111,28 @@ void vmw_resource_unreference(struct vmw_resource **p_res) write_unlock(&dev_priv->resource_lock); } - -/** - * vmw_resource_alloc_id - release a resource id to the id manager. - * - * @dev_priv: Pointer to the device private structure. - * @res: Pointer to the resource. - * - * Allocate the lowest free resource from the resource manager, and set - * @res->id to that id. Returns 0 on success and -ENOMEM on failure. - */ -static int vmw_resource_alloc_id(struct vmw_private *dev_priv, - struct vmw_resource *res) +static int vmw_resource_init(struct vmw_private *dev_priv, + struct vmw_resource *res, + struct idr *idr, + enum ttm_object_type obj_type, + void (*res_free) (struct vmw_resource *res)) { int ret; - BUG_ON(res->id != -1); + kref_init(&res->kref); + res->hw_destroy = NULL; + res->res_free = res_free; + res->res_type = obj_type; + res->idr = idr; + res->avail = false; + res->dev_priv = dev_priv; do { - if (unlikely(idr_pre_get(res->idr, GFP_KERNEL) == 0)) + if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) return -ENOMEM; write_lock(&dev_priv->resource_lock); - ret = idr_get_new_above(res->idr, res, 1, &res->id); + ret = idr_get_new_above(idr, res, 1, &res->id); write_unlock(&dev_priv->resource_lock); } while (ret == -EAGAIN); @@ -179,33 +140,6 @@ static int vmw_resource_alloc_id(struct vmw_private *dev_priv, return ret; } - -static int vmw_resource_init(struct vmw_private *dev_priv, - struct vmw_resource *res, - struct idr *idr, - enum ttm_object_type obj_type, - bool delay_id, - void (*res_free) (struct vmw_resource *res), - void (*remove_from_lists) - (struct vmw_resource *res)) -{ - kref_init(&res->kref); - res->hw_destroy = NULL; - res->res_free = res_free; - res->remove_from_lists = remove_from_lists; - res->res_type = obj_type; - res->idr = idr; - res->avail = false; - res->dev_priv = dev_priv; - INIT_LIST_HEAD(&res->query_head); - INIT_LIST_HEAD(&res->validate_head); - res->id = -1; - if (delay_id) - return 0; - else - return vmw_resource_alloc_id(dev_priv, res); -} - /** * vmw_resource_activate * @@ -260,12 +194,8 @@ static void vmw_hw_context_destroy(struct vmw_resource *res) struct { SVGA3dCmdHeader header; SVGA3dCmdDestroyContext body; - } *cmd; - + } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - vmw_execbuf_release_pinned_bo(dev_priv, true, res->id); - - cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); if (unlikely(cmd == NULL)) { DRM_ERROR("Failed reserving FIFO space for surface " "destruction.\n"); @@ -292,17 +222,14 @@ static int vmw_context_init(struct vmw_private *dev_priv, } *cmd; ret = vmw_resource_init(dev_priv, res, &dev_priv->context_idr, - VMW_RES_CONTEXT, false, res_free, NULL); + VMW_RES_CONTEXT, res_free); if (unlikely(ret != 0)) { - DRM_ERROR("Failed to allocate a resource id.\n"); - goto out_early; - } - - if (unlikely(res->id >= SVGA3D_MAX_CONTEXT_IDS)) { - DRM_ERROR("Out of hw context ids.\n"); - vmw_resource_unreference(&res); - return -ENOMEM; + if (res_free == NULL) + kfree(res); + else + res_free(res); + return ret; } cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); @@ -320,13 +247,6 @@ static int vmw_context_init(struct vmw_private *dev_priv, (void) vmw_3d_resource_inc(dev_priv, false); vmw_resource_activate(res, vmw_hw_context_destroy); return 0; - -out_early: - if (res_free == NULL) - kfree(res); - else - res_free(res); - return ret; } struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv) @@ -349,11 +269,8 @@ static void vmw_user_context_free(struct vmw_resource *res) { struct vmw_user_context *ctx = container_of(res, struct vmw_user_context, res); - struct vmw_private *dev_priv = res->dev_priv; kfree(ctx); - ttm_mem_global_free(vmw_mem_glob(dev_priv), - vmw_user_context_size); } /** @@ -407,56 +324,23 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_user_context *ctx; + struct vmw_user_context *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); struct vmw_resource *res; struct vmw_resource *tmp; struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_master *vmaster = vmw_master(file_priv->master); int ret; - - /* - * Approximate idr memory usage with 128 bytes. It will be limited - * by maximum number_of contexts anyway. - */ - - if (unlikely(vmw_user_context_size == 0)) - vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128; - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), - vmw_user_context_size, - false, true); - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Out of graphics memory for context" - " creation.\n"); - goto out_unlock; - } - - ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); - if (unlikely(ctx == NULL)) { - ttm_mem_global_free(vmw_mem_glob(dev_priv), - vmw_user_context_size); - ret = -ENOMEM; - goto out_unlock; - } + if (unlikely(ctx == NULL)) + return -ENOMEM; res = &ctx->res; ctx->base.shareable = false; ctx->base.tfile = NULL; - /* - * From here on, the destructor takes over resource freeing. - */ - ret = vmw_context_init(dev_priv, res, vmw_user_context_free); if (unlikely(ret != 0)) - goto out_unlock; + return ret; tmp = vmw_resource_reference(&ctx->res); ret = ttm_base_object_init(tfile, &ctx->base, false, VMW_RES_CONTEXT, @@ -470,8 +354,6 @@ int vmw_context_define_ioctl(struct drm_device *dev, void *data, arg->cid = res->id; out_err: vmw_resource_unreference(&res); -out_unlock: - ttm_read_unlock(&vmaster->lock); return ret; } @@ -500,285 +382,31 @@ int vmw_context_check(struct vmw_private *dev_priv, return ret; } -struct vmw_bpp { - uint8_t bpp; - uint8_t s_bpp; -}; - -/* - * Size table for the supported SVGA3D surface formats. It consists of - * two values. The bpp value and the s_bpp value which is short for - * "stride bits per pixel" The values are given in such a way that the - * minimum stride for the image is calculated using - * - * min_stride = w*s_bpp - * - * and the total memory requirement for the image is - * - * h*min_stride*bpp/s_bpp - * - */ -static const struct vmw_bpp vmw_sf_bpp[] = { - [SVGA3D_FORMAT_INVALID] = {0, 0}, - [SVGA3D_X8R8G8B8] = {32, 32}, - [SVGA3D_A8R8G8B8] = {32, 32}, - [SVGA3D_R5G6B5] = {16, 16}, - [SVGA3D_X1R5G5B5] = {16, 16}, - [SVGA3D_A1R5G5B5] = {16, 16}, - [SVGA3D_A4R4G4B4] = {16, 16}, - [SVGA3D_Z_D32] = {32, 32}, - [SVGA3D_Z_D16] = {16, 16}, - [SVGA3D_Z_D24S8] = {32, 32}, - [SVGA3D_Z_D15S1] = {16, 16}, - [SVGA3D_LUMINANCE8] = {8, 8}, - [SVGA3D_LUMINANCE4_ALPHA4] = {8, 8}, - [SVGA3D_LUMINANCE16] = {16, 16}, - [SVGA3D_LUMINANCE8_ALPHA8] = {16, 16}, - [SVGA3D_DXT1] = {4, 16}, - [SVGA3D_DXT2] = {8, 32}, - [SVGA3D_DXT3] = {8, 32}, - [SVGA3D_DXT4] = {8, 32}, - [SVGA3D_DXT5] = {8, 32}, - [SVGA3D_BUMPU8V8] = {16, 16}, - [SVGA3D_BUMPL6V5U5] = {16, 16}, - [SVGA3D_BUMPX8L8V8U8] = {32, 32}, - [SVGA3D_ARGB_S10E5] = {16, 16}, - [SVGA3D_ARGB_S23E8] = {32, 32}, - [SVGA3D_A2R10G10B10] = {32, 32}, - [SVGA3D_V8U8] = {16, 16}, - [SVGA3D_Q8W8V8U8] = {32, 32}, - [SVGA3D_CxV8U8] = {16, 16}, - [SVGA3D_X8L8V8U8] = {32, 32}, - [SVGA3D_A2W10V10U10] = {32, 32}, - [SVGA3D_ALPHA8] = {8, 8}, - [SVGA3D_R_S10E5] = {16, 16}, - [SVGA3D_R_S23E8] = {32, 32}, - [SVGA3D_RG_S10E5] = {16, 16}, - [SVGA3D_RG_S23E8] = {32, 32}, - [SVGA3D_BUFFER] = {8, 8}, - [SVGA3D_Z_D24X8] = {32, 32}, - [SVGA3D_V16U16] = {32, 32}, - [SVGA3D_G16R16] = {32, 32}, - [SVGA3D_A16B16G16R16] = {64, 64}, - [SVGA3D_UYVY] = {12, 12}, - [SVGA3D_YUY2] = {12, 12}, - [SVGA3D_NV12] = {12, 8}, - [SVGA3D_AYUV] = {32, 32}, - [SVGA3D_BC4_UNORM] = {4, 16}, - [SVGA3D_BC5_UNORM] = {8, 32}, - [SVGA3D_Z_DF16] = {16, 16}, - [SVGA3D_Z_DF24] = {24, 24}, - [SVGA3D_Z_D24S8_INT] = {32, 32} -}; - /** * Surface management. */ -struct vmw_surface_dma { - SVGA3dCmdHeader header; - SVGA3dCmdSurfaceDMA body; - SVGA3dCopyBox cb; - SVGA3dCmdSurfaceDMASuffix suffix; -}; - -struct vmw_surface_define { - SVGA3dCmdHeader header; - SVGA3dCmdDefineSurface body; -}; - -struct vmw_surface_destroy { - SVGA3dCmdHeader header; - SVGA3dCmdDestroySurface body; -}; - - -/** - * vmw_surface_dma_size - Compute fifo size for a dma command. - * - * @srf: Pointer to a struct vmw_surface - * - * Computes the required size for a surface dma command for backup or - * restoration of the surface represented by @srf. - */ -static inline uint32_t vmw_surface_dma_size(const struct vmw_surface *srf) -{ - return srf->num_sizes * sizeof(struct vmw_surface_dma); -} - - -/** - * vmw_surface_define_size - Compute fifo size for a surface define command. - * - * @srf: Pointer to a struct vmw_surface - * - * Computes the required size for a surface define command for the definition - * of the surface represented by @srf. - */ -static inline uint32_t vmw_surface_define_size(const struct vmw_surface *srf) -{ - return sizeof(struct vmw_surface_define) + srf->num_sizes * - sizeof(SVGA3dSize); -} - - -/** - * vmw_surface_destroy_size - Compute fifo size for a surface destroy command. - * - * Computes the required size for a surface destroy command for the destruction - * of a hw surface. - */ -static inline uint32_t vmw_surface_destroy_size(void) -{ - return sizeof(struct vmw_surface_destroy); -} - -/** - * vmw_surface_destroy_encode - Encode a surface_destroy command. - * - * @id: The surface id - * @cmd_space: Pointer to memory area in which the commands should be encoded. - */ -static void vmw_surface_destroy_encode(uint32_t id, - void *cmd_space) -{ - struct vmw_surface_destroy *cmd = (struct vmw_surface_destroy *) - cmd_space; - - cmd->header.id = SVGA_3D_CMD_SURFACE_DESTROY; - cmd->header.size = sizeof(cmd->body); - cmd->body.sid = id; -} - -/** - * vmw_surface_define_encode - Encode a surface_define command. - * - * @srf: Pointer to a struct vmw_surface object. - * @cmd_space: Pointer to memory area in which the commands should be encoded. - */ -static void vmw_surface_define_encode(const struct vmw_surface *srf, - void *cmd_space) -{ - struct vmw_surface_define *cmd = (struct vmw_surface_define *) - cmd_space; - struct drm_vmw_size *src_size; - SVGA3dSize *cmd_size; - uint32_t cmd_len; - int i; - - cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize); - - cmd->header.id = SVGA_3D_CMD_SURFACE_DEFINE; - cmd->header.size = cmd_len; - cmd->body.sid = srf->res.id; - cmd->body.surfaceFlags = srf->flags; - cmd->body.format = cpu_to_le32(srf->format); - for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) - cmd->body.face[i].numMipLevels = srf->mip_levels[i]; - - cmd += 1; - cmd_size = (SVGA3dSize *) cmd; - src_size = srf->sizes; - - for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) { - cmd_size->width = src_size->width; - cmd_size->height = src_size->height; - cmd_size->depth = src_size->depth; - } -} - - -/** - * vmw_surface_dma_encode - Encode a surface_dma command. - * - * @srf: Pointer to a struct vmw_surface object. - * @cmd_space: Pointer to memory area in which the commands should be encoded. - * @ptr: Pointer to an SVGAGuestPtr indicating where the surface contents - * should be placed or read from. - * @to_surface: Boolean whether to DMA to the surface or from the surface. - */ -static void vmw_surface_dma_encode(struct vmw_surface *srf, - void *cmd_space, - const SVGAGuestPtr *ptr, - bool to_surface) -{ - uint32_t i; - uint32_t bpp = vmw_sf_bpp[srf->format].bpp; - uint32_t stride_bpp = vmw_sf_bpp[srf->format].s_bpp; - struct vmw_surface_dma *cmd = (struct vmw_surface_dma *)cmd_space; - - for (i = 0; i < srf->num_sizes; ++i) { - SVGA3dCmdHeader *header = &cmd->header; - SVGA3dCmdSurfaceDMA *body = &cmd->body; - SVGA3dCopyBox *cb = &cmd->cb; - SVGA3dCmdSurfaceDMASuffix *suffix = &cmd->suffix; - const struct vmw_surface_offset *cur_offset = &srf->offsets[i]; - const struct drm_vmw_size *cur_size = &srf->sizes[i]; - - header->id = SVGA_3D_CMD_SURFACE_DMA; - header->size = sizeof(*body) + sizeof(*cb) + sizeof(*suffix); - - body->guest.ptr = *ptr; - body->guest.ptr.offset += cur_offset->bo_offset; - body->guest.pitch = (cur_size->width * stride_bpp + 7) >> 3; - body->host.sid = srf->res.id; - body->host.face = cur_offset->face; - body->host.mipmap = cur_offset->mip; - body->transfer = ((to_surface) ? SVGA3D_WRITE_HOST_VRAM : - SVGA3D_READ_HOST_VRAM); - cb->x = 0; - cb->y = 0; - cb->z = 0; - cb->srcx = 0; - cb->srcy = 0; - cb->srcz = 0; - cb->w = cur_size->width; - cb->h = cur_size->height; - cb->d = cur_size->depth; - - suffix->suffixSize = sizeof(*suffix); - suffix->maximumOffset = body->guest.pitch*cur_size->height* - cur_size->depth*bpp / stride_bpp; - suffix->flags.discard = 0; - suffix->flags.unsynchronized = 0; - suffix->flags.reserved = 0; - ++cmd; - } -}; - - static void vmw_hw_surface_destroy(struct vmw_resource *res) { struct vmw_private *dev_priv = res->dev_priv; - struct vmw_surface *srf; - void *cmd; - - if (res->id != -1) { - - cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size()); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for surface " - "destruction.\n"); - return; - } - - vmw_surface_destroy_encode(res->id, cmd); - vmw_fifo_commit(dev_priv, vmw_surface_destroy_size()); + struct { + SVGA3dCmdHeader header; + SVGA3dCmdDestroySurface body; + } *cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); - /* - * used_memory_size_atomic, or separate lock - * to avoid taking dev_priv::cmdbuf_mutex in - * the destroy path. - */ + if (unlikely(cmd == NULL)) { + DRM_ERROR("Failed reserving FIFO space for surface " + "destruction.\n"); + return; + } - mutex_lock(&dev_priv->cmdbuf_mutex); - srf = container_of(res, struct vmw_surface, res); - dev_priv->used_memory_size -= srf->backup_size; - mutex_unlock(&dev_priv->cmdbuf_mutex); + cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DESTROY); + cmd->header.size = cpu_to_le32(sizeof(cmd->body)); + cmd->body.sid = cpu_to_le32(res->id); - } + vmw_fifo_commit(dev_priv, sizeof(*cmd)); vmw_3d_resource_dec(dev_priv, false); } @@ -786,352 +414,70 @@ void vmw_surface_res_free(struct vmw_resource *res) { struct vmw_surface *srf = container_of(res, struct vmw_surface, res); - if (srf->backup) - ttm_bo_unref(&srf->backup); - kfree(srf->offsets); kfree(srf->sizes); kfree(srf->snooper.image); kfree(srf); } - -/** - * vmw_surface_do_validate - make a surface available to the device. - * - * @dev_priv: Pointer to a device private struct. - * @srf: Pointer to a struct vmw_surface. - * - * If the surface doesn't have a hw id, allocate one, and optionally - * DMA the backed up surface contents to the device. - * - * Returns -EBUSY if there wasn't sufficient device resources to - * complete the validation. Retry after freeing up resources. - * - * May return other errors if the kernel is out of guest resources. - */ -int vmw_surface_do_validate(struct vmw_private *dev_priv, - struct vmw_surface *srf) +int vmw_surface_init(struct vmw_private *dev_priv, + struct vmw_surface *srf, + void (*res_free) (struct vmw_resource *res)) { - struct vmw_resource *res = &srf->res; - struct list_head val_list; - struct ttm_validate_buffer val_buf; - uint32_t submit_size; - uint8_t *cmd; int ret; + struct { + SVGA3dCmdHeader header; + SVGA3dCmdDefineSurface body; + } *cmd; + SVGA3dSize *cmd_size; + struct vmw_resource *res = &srf->res; + struct drm_vmw_size *src_size; + size_t submit_size; + uint32_t cmd_len; + int i; - if (likely(res->id != -1)) - return 0; - - if (unlikely(dev_priv->used_memory_size + srf->backup_size >= - dev_priv->memory_size)) - return -EBUSY; - - /* - * Reserve- and validate the backup DMA bo. - */ - - if (srf->backup) { - INIT_LIST_HEAD(&val_list); - val_buf.bo = ttm_bo_reference(srf->backup); - val_buf.new_sync_obj_arg = (void *)((unsigned long) - DRM_VMW_FENCE_FLAG_EXEC); - list_add_tail(&val_buf.head, &val_list); - ret = ttm_eu_reserve_buffers(&val_list); - if (unlikely(ret != 0)) - goto out_no_reserve; - - ret = ttm_bo_validate(srf->backup, &vmw_srf_placement, - true, false, false); - if (unlikely(ret != 0)) - goto out_no_validate; - } - - /* - * Alloc id for the resource. - */ + BUG_ON(res_free == NULL); + ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, + VMW_RES_SURFACE, res_free); - ret = vmw_resource_alloc_id(dev_priv, res); if (unlikely(ret != 0)) { - DRM_ERROR("Failed to allocate a surface id.\n"); - goto out_no_id; - } - if (unlikely(res->id >= SVGA3D_MAX_SURFACE_IDS)) { - ret = -EBUSY; - goto out_no_fifo; + res_free(res); + return ret; } - - /* - * Encode surface define- and dma commands. - */ - - submit_size = vmw_surface_define_size(srf); - if (srf->backup) - submit_size += vmw_surface_dma_size(srf); + submit_size = sizeof(*cmd) + srf->num_sizes * sizeof(SVGA3dSize); + cmd_len = sizeof(cmd->body) + srf->num_sizes * sizeof(SVGA3dSize); cmd = vmw_fifo_reserve(dev_priv, submit_size); if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for surface " - "validation.\n"); - ret = -ENOMEM; - goto out_no_fifo; - } - - vmw_surface_define_encode(srf, cmd); - if (srf->backup) { - SVGAGuestPtr ptr; - - cmd += vmw_surface_define_size(srf); - vmw_bo_get_guest_ptr(srf->backup, &ptr); - vmw_surface_dma_encode(srf, cmd, &ptr, true); - } - - vmw_fifo_commit(dev_priv, submit_size); - - /* - * Create a fence object and fence the backup buffer. - */ - - if (srf->backup) { - struct vmw_fence_obj *fence; - - (void) vmw_execbuf_fence_commands(NULL, dev_priv, - &fence, NULL); - ttm_eu_fence_buffer_objects(&val_list, fence); - if (likely(fence != NULL)) - vmw_fence_obj_unreference(&fence); - ttm_bo_unref(&val_buf.bo); - ttm_bo_unref(&srf->backup); + DRM_ERROR("Fifo reserve failed for create surface.\n"); + vmw_resource_unreference(&res); + return -ENOMEM; } - /* - * Surface memory usage accounting. - */ - - dev_priv->used_memory_size += srf->backup_size; - - return 0; - -out_no_fifo: - vmw_resource_release_id(res); -out_no_id: -out_no_validate: - if (srf->backup) - ttm_eu_backoff_reservation(&val_list); -out_no_reserve: - if (srf->backup) - ttm_bo_unref(&val_buf.bo); - return ret; -} - -/** - * vmw_surface_evict - Evict a hw surface. - * - * @dev_priv: Pointer to a device private struct. - * @srf: Pointer to a struct vmw_surface - * - * DMA the contents of a hw surface to a backup guest buffer object, - * and destroy the hw surface, releasing its id. - */ -int vmw_surface_evict(struct vmw_private *dev_priv, - struct vmw_surface *srf) -{ - struct vmw_resource *res = &srf->res; - struct list_head val_list; - struct ttm_validate_buffer val_buf; - uint32_t submit_size; - uint8_t *cmd; - int ret; - struct vmw_fence_obj *fence; - SVGAGuestPtr ptr; - - BUG_ON(res->id == -1); - - /* - * Create a surface backup buffer object. - */ - - if (!srf->backup) { - ret = ttm_bo_create(&dev_priv->bdev, srf->backup_size, - ttm_bo_type_device, - &vmw_srf_placement, 0, 0, true, - NULL, &srf->backup); - if (unlikely(ret != 0)) - return ret; + cmd->header.id = cpu_to_le32(SVGA_3D_CMD_SURFACE_DEFINE); + cmd->header.size = cpu_to_le32(cmd_len); + cmd->body.sid = cpu_to_le32(res->id); + cmd->body.surfaceFlags = cpu_to_le32(srf->flags); + cmd->body.format = cpu_to_le32(srf->format); + for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { + cmd->body.face[i].numMipLevels = + cpu_to_le32(srf->mip_levels[i]); } - /* - * Reserve- and validate the backup DMA bo. - */ - - INIT_LIST_HEAD(&val_list); - val_buf.bo = ttm_bo_reference(srf->backup); - val_buf.new_sync_obj_arg = (void *)(unsigned long) - DRM_VMW_FENCE_FLAG_EXEC; - list_add_tail(&val_buf.head, &val_list); - ret = ttm_eu_reserve_buffers(&val_list); - if (unlikely(ret != 0)) - goto out_no_reserve; - - ret = ttm_bo_validate(srf->backup, &vmw_srf_placement, - true, false, false); - if (unlikely(ret != 0)) - goto out_no_validate; - - - /* - * Encode the dma- and surface destroy commands. - */ + cmd += 1; + cmd_size = (SVGA3dSize *) cmd; + src_size = srf->sizes; - submit_size = vmw_surface_dma_size(srf) + vmw_surface_destroy_size(); - cmd = vmw_fifo_reserve(dev_priv, submit_size); - if (unlikely(cmd == NULL)) { - DRM_ERROR("Failed reserving FIFO space for surface " - "eviction.\n"); - ret = -ENOMEM; - goto out_no_fifo; + for (i = 0; i < srf->num_sizes; ++i, cmd_size++, src_size++) { + cmd_size->width = cpu_to_le32(src_size->width); + cmd_size->height = cpu_to_le32(src_size->height); + cmd_size->depth = cpu_to_le32(src_size->depth); } - vmw_bo_get_guest_ptr(srf->backup, &ptr); - vmw_surface_dma_encode(srf, cmd, &ptr, false); - cmd += vmw_surface_dma_size(srf); - vmw_surface_destroy_encode(res->id, cmd); vmw_fifo_commit(dev_priv, submit_size); - - /* - * Surface memory usage accounting. - */ - - dev_priv->used_memory_size -= srf->backup_size; - - /* - * Create a fence object and fence the DMA buffer. - */ - - (void) vmw_execbuf_fence_commands(NULL, dev_priv, - &fence, NULL); - ttm_eu_fence_buffer_objects(&val_list, fence); - if (likely(fence != NULL)) - vmw_fence_obj_unreference(&fence); - ttm_bo_unref(&val_buf.bo); - - /* - * Release the surface ID. - */ - - vmw_resource_release_id(res); - - return 0; - -out_no_fifo: -out_no_validate: - if (srf->backup) - ttm_eu_backoff_reservation(&val_list); -out_no_reserve: - ttm_bo_unref(&val_buf.bo); - ttm_bo_unref(&srf->backup); - return ret; -} - - -/** - * vmw_surface_validate - make a surface available to the device, evicting - * other surfaces if needed. - * - * @dev_priv: Pointer to a device private struct. - * @srf: Pointer to a struct vmw_surface. - * - * Try to validate a surface and if it fails due to limited device resources, - * repeatedly try to evict other surfaces until the request can be - * acommodated. - * - * May return errors if out of resources. - */ -int vmw_surface_validate(struct vmw_private *dev_priv, - struct vmw_surface *srf) -{ - int ret; - struct vmw_surface *evict_srf; - - do { - write_lock(&dev_priv->resource_lock); - list_del_init(&srf->lru_head); - write_unlock(&dev_priv->resource_lock); - - ret = vmw_surface_do_validate(dev_priv, srf); - if (likely(ret != -EBUSY)) - break; - - write_lock(&dev_priv->resource_lock); - if (list_empty(&dev_priv->surface_lru)) { - DRM_ERROR("Out of device memory for surfaces.\n"); - ret = -EBUSY; - write_unlock(&dev_priv->resource_lock); - break; - } - - evict_srf = vmw_surface_reference - (list_first_entry(&dev_priv->surface_lru, - struct vmw_surface, - lru_head)); - list_del_init(&evict_srf->lru_head); - - write_unlock(&dev_priv->resource_lock); - (void) vmw_surface_evict(dev_priv, evict_srf); - - vmw_surface_unreference(&evict_srf); - - } while (1); - - if (unlikely(ret != 0 && srf->res.id != -1)) { - write_lock(&dev_priv->resource_lock); - list_add_tail(&srf->lru_head, &dev_priv->surface_lru); - write_unlock(&dev_priv->resource_lock); - } - - return ret; -} - - -/** - * vmw_surface_remove_from_lists - Remove surface resources from lookup lists - * - * @res: Pointer to a struct vmw_resource embedded in a struct vmw_surface - * - * As part of the resource destruction, remove the surface from any - * lookup lists. - */ -static void vmw_surface_remove_from_lists(struct vmw_resource *res) -{ - struct vmw_surface *srf = container_of(res, struct vmw_surface, res); - - list_del_init(&srf->lru_head); -} - -int vmw_surface_init(struct vmw_private *dev_priv, - struct vmw_surface *srf, - void (*res_free) (struct vmw_resource *res)) -{ - int ret; - struct vmw_resource *res = &srf->res; - - BUG_ON(res_free == NULL); - INIT_LIST_HEAD(&srf->lru_head); - ret = vmw_resource_init(dev_priv, res, &dev_priv->surface_idr, - VMW_RES_SURFACE, true, res_free, - vmw_surface_remove_from_lists); - - if (unlikely(ret != 0)) - res_free(res); - - /* - * The surface won't be visible to hardware until a - * surface validate. - */ - (void) vmw_3d_resource_inc(dev_priv, false); vmw_resource_activate(res, vmw_hw_surface_destroy); - return ret; + return 0; } static void vmw_user_surface_free(struct vmw_resource *res) @@ -1139,58 +485,12 @@ static void vmw_user_surface_free(struct vmw_resource *res) struct vmw_surface *srf = container_of(res, struct vmw_surface, res); struct vmw_user_surface *user_srf = container_of(srf, struct vmw_user_surface, srf); - struct vmw_private *dev_priv = srf->res.dev_priv; - uint32_t size = user_srf->size; - if (srf->backup) - ttm_bo_unref(&srf->backup); - kfree(srf->offsets); kfree(srf->sizes); kfree(srf->snooper.image); kfree(user_srf); - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); -} - -/** - * vmw_resource_unreserve - unreserve resources previously reserved for - * command submission. - * - * @list_head: list of resources to unreserve. - * - * Currently only surfaces are considered, and unreserving a surface - * means putting it back on the device's surface lru list, - * so that it can be evicted if necessary. - * This function traverses the resource list and - * checks whether resources are surfaces, and in that case puts them back - * on the device's surface LRU list. - */ -void vmw_resource_unreserve(struct list_head *list) -{ - struct vmw_resource *res; - struct vmw_surface *srf; - rwlock_t *lock = NULL; - - list_for_each_entry(res, list, validate_head) { - - if (res->res_free != &vmw_surface_res_free && - res->res_free != &vmw_user_surface_free) - continue; - - if (unlikely(lock == NULL)) { - lock = &res->dev_priv->resource_lock; - write_lock(lock); - } - - srf = container_of(res, struct vmw_surface, res); - list_del_init(&srf->lru_head); - list_add_tail(&srf->lru_head, &res->dev_priv->surface_lru); - } - - if (lock != NULL) - write_unlock(lock); } - int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, struct ttm_object_file *tfile, uint32_t handle, struct vmw_surface **out) @@ -1267,51 +567,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct drm_vmw_size __user *user_sizes; int ret; - int i, j; - uint32_t cur_bo_offset; - struct drm_vmw_size *cur_size; - struct vmw_surface_offset *cur_offset; - uint32_t stride_bpp; - uint32_t bpp; - uint32_t num_sizes; - uint32_t size; - struct vmw_master *vmaster = vmw_master(file_priv->master); - - if (unlikely(vmw_user_surface_size == 0)) - vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + - 128; - - num_sizes = 0; - for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) - num_sizes += req->mip_levels[i]; - - if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * - DRM_VMW_MAX_MIP_LEVELS) - return -EINVAL; - - size = vmw_user_surface_size + 128 + - ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) + - ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset)); - - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), - size, false, true); - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Out of graphics memory for surface" - " creation.\n"); - goto out_unlock; - } + int i; - user_srf = kmalloc(sizeof(*user_srf), GFP_KERNEL); - if (unlikely(user_srf == NULL)) { - ret = -ENOMEM; - goto out_no_user_srf; - } + if (unlikely(user_srf == NULL)) + return -ENOMEM; srf = &user_srf->srf; res = &srf->res; @@ -1319,22 +578,21 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, srf->flags = req->flags; srf->format = req->format; srf->scanout = req->scanout; - srf->backup = NULL; - memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); - srf->num_sizes = num_sizes; - user_srf->size = size; + srf->num_sizes = 0; + for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) + srf->num_sizes += srf->mip_levels[i]; - srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); - if (unlikely(srf->sizes == NULL)) { - ret = -ENOMEM; - goto out_no_sizes; + if (srf->num_sizes > DRM_VMW_MAX_SURFACE_FACES * + DRM_VMW_MAX_MIP_LEVELS) { + ret = -EINVAL; + goto out_err0; } - srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets), - GFP_KERNEL); + + srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); if (unlikely(srf->sizes == NULL)) { ret = -ENOMEM; - goto out_no_offsets; + goto out_err0; } user_sizes = (struct drm_vmw_size __user *)(unsigned long) @@ -1344,32 +602,9 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, srf->num_sizes * sizeof(*srf->sizes)); if (unlikely(ret != 0)) { ret = -EFAULT; - goto out_no_copy; + goto out_err1; } - cur_bo_offset = 0; - cur_offset = srf->offsets; - cur_size = srf->sizes; - - bpp = vmw_sf_bpp[srf->format].bpp; - stride_bpp = vmw_sf_bpp[srf->format].s_bpp; - - for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { - for (j = 0; j < srf->mip_levels[i]; ++j) { - uint32_t stride = - (cur_size->width * stride_bpp + 7) >> 3; - - cur_offset->face = i; - cur_offset->mip = j; - cur_offset->bo_offset = cur_bo_offset; - cur_bo_offset += stride * cur_size->height * - cur_size->depth * bpp / stride_bpp; - ++cur_offset; - ++cur_size; - } - } - srf->backup_size = cur_bo_offset; - if (srf->scanout && srf->num_sizes == 1 && srf->sizes[0].width == 64 && @@ -1381,7 +616,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, if (!srf->snooper.image) { DRM_ERROR("Failed to allocate cursor_image\n"); ret = -ENOMEM; - goto out_no_copy; + goto out_err1; } } else { srf->snooper.image = NULL; @@ -1398,7 +633,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); if (unlikely(ret != 0)) - goto out_unlock; + return ret; tmp = vmw_resource_reference(&srf->res); ret = ttm_base_object_init(tfile, &user_srf->base, @@ -1408,7 +643,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, if (unlikely(ret != 0)) { vmw_resource_unreference(&tmp); vmw_resource_unreference(&res); - goto out_unlock; + return ret; } rep->sid = user_srf->base.hash.key; @@ -1416,19 +651,11 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, DRM_ERROR("Created bad Surface ID.\n"); vmw_resource_unreference(&res); - - ttm_read_unlock(&vmaster->lock); return 0; -out_no_copy: - kfree(srf->offsets); -out_no_offsets: +out_err1: kfree(srf->sizes); -out_no_sizes: +out_err0: kfree(user_srf); -out_no_user_srf: - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); -out_unlock: - ttm_read_unlock(&vmaster->lock); return ret; } @@ -1742,7 +969,7 @@ static int vmw_stream_init(struct vmw_private *dev_priv, int ret; ret = vmw_resource_init(dev_priv, res, &dev_priv->stream_idr, - VMW_RES_STREAM, false, res_free, NULL); + VMW_RES_STREAM, res_free); if (unlikely(ret != 0)) { if (res_free == NULL) @@ -1772,11 +999,8 @@ static void vmw_user_stream_free(struct vmw_resource *res) { struct vmw_user_stream *stream = container_of(res, struct vmw_user_stream, stream.res); - struct vmw_private *dev_priv = res->dev_priv; kfree(stream); - ttm_mem_global_free(vmw_mem_glob(dev_priv), - vmw_user_stream_size); } /** @@ -1830,56 +1054,23 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_user_stream *stream; + struct vmw_user_stream *stream = kmalloc(sizeof(*stream), GFP_KERNEL); struct vmw_resource *res; struct vmw_resource *tmp; struct drm_vmw_stream_arg *arg = (struct drm_vmw_stream_arg *)data; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_master *vmaster = vmw_master(file_priv->master); int ret; - /* - * Approximate idr memory usage with 128 bytes. It will be limited - * by maximum number_of streams anyway? - */ - - if (unlikely(vmw_user_stream_size == 0)) - vmw_user_stream_size = ttm_round_pot(sizeof(*stream)) + 128; - - ret = ttm_read_lock(&vmaster->lock, true); - if (unlikely(ret != 0)) - return ret; - - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), - vmw_user_stream_size, - false, true); - if (unlikely(ret != 0)) { - if (ret != -ERESTARTSYS) - DRM_ERROR("Out of graphics memory for stream" - " creation.\n"); - goto out_unlock; - } - - - stream = kmalloc(sizeof(*stream), GFP_KERNEL); - if (unlikely(stream == NULL)) { - ttm_mem_global_free(vmw_mem_glob(dev_priv), - vmw_user_stream_size); - ret = -ENOMEM; - goto out_unlock; - } + if (unlikely(stream == NULL)) + return -ENOMEM; res = &stream->stream.res; stream->base.shareable = false; stream->base.tfile = NULL; - /* - * From here on, the destructor takes over resource freeing. - */ - ret = vmw_stream_init(dev_priv, &stream->stream, vmw_user_stream_free); if (unlikely(ret != 0)) - goto out_unlock; + return ret; tmp = vmw_resource_reference(res); ret = ttm_base_object_init(tfile, &stream->base, false, VMW_RES_STREAM, @@ -1893,8 +1084,6 @@ int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, arg->stream_id = res->id; out_err: vmw_resource_unreference(&res); -out_unlock: - ttm_read_unlock(&vmaster->lock); return ret; } diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c deleted file mode 100644 index 347e40699443..000000000000 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ /dev/null @@ -1,566 +0,0 @@ -/************************************************************************** - * - * Copyright © 2011 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "vmwgfx_kms.h" - - -#define vmw_crtc_to_sou(x) \ - container_of(x, struct vmw_screen_object_unit, base.crtc) -#define vmw_encoder_to_sou(x) \ - container_of(x, struct vmw_screen_object_unit, base.encoder) -#define vmw_connector_to_sou(x) \ - container_of(x, struct vmw_screen_object_unit, base.connector) - -struct vmw_screen_object_display { - struct list_head active; - - unsigned num_active; - unsigned last_num_active; - - struct vmw_framebuffer *fb; -}; - -/** - * Display unit using screen objects. - */ -struct vmw_screen_object_unit { - struct vmw_display_unit base; - - unsigned long buffer_size; /**< Size of allocated buffer */ - struct vmw_dma_buffer *buffer; /**< Backing store buffer */ - - bool defined; - - struct list_head active; -}; - -static void vmw_sou_destroy(struct vmw_screen_object_unit *sou) -{ - list_del_init(&sou->active); - vmw_display_unit_cleanup(&sou->base); - kfree(sou); -} - - -/* - * Screen Object Display Unit CRTC functions - */ - -static void vmw_sou_crtc_destroy(struct drm_crtc *crtc) -{ - vmw_sou_destroy(vmw_crtc_to_sou(crtc)); -} - -static int vmw_sou_del_active(struct vmw_private *vmw_priv, - struct vmw_screen_object_unit *sou) -{ - struct vmw_screen_object_display *ld = vmw_priv->sou_priv; - if (list_empty(&sou->active)) - return 0; - - /* Must init otherwise list_empty(&sou->active) will not work. */ - list_del_init(&sou->active); - if (--(ld->num_active) == 0) { - BUG_ON(!ld->fb); - if (ld->fb->unpin) - ld->fb->unpin(ld->fb); - ld->fb = NULL; - } - - return 0; -} - -static int vmw_sou_add_active(struct vmw_private *vmw_priv, - struct vmw_screen_object_unit *sou, - struct vmw_framebuffer *vfb) -{ - struct vmw_screen_object_display *ld = vmw_priv->sou_priv; - struct vmw_screen_object_unit *entry; - struct list_head *at; - - BUG_ON(!ld->num_active && ld->fb); - if (vfb != ld->fb) { - if (ld->fb && ld->fb->unpin) - ld->fb->unpin(ld->fb); - if (vfb->pin) - vfb->pin(vfb); - ld->fb = vfb; - } - - if (!list_empty(&sou->active)) - return 0; - - at = &ld->active; - list_for_each_entry(entry, &ld->active, active) { - if (entry->base.unit > sou->base.unit) - break; - - at = &entry->active; - } - - list_add(&sou->active, at); - - ld->num_active++; - - return 0; -} - -/** - * Send the fifo command to create a screen. - */ -static int vmw_sou_fifo_create(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou, - uint32_t x, uint32_t y, - struct drm_display_mode *mode) -{ - size_t fifo_size; - - struct { - struct { - uint32_t cmdType; - } header; - SVGAScreenObject obj; - } *cmd; - - BUG_ON(!sou->buffer); - - fifo_size = sizeof(*cmd); - cmd = vmw_fifo_reserve(dev_priv, fifo_size); - /* The hardware has hung, nothing we can do about it here. */ - if (unlikely(cmd == NULL)) { - DRM_ERROR("Fifo reserve failed.\n"); - return -ENOMEM; - } - - memset(cmd, 0, fifo_size); - cmd->header.cmdType = SVGA_CMD_DEFINE_SCREEN; - cmd->obj.structSize = sizeof(SVGAScreenObject); - cmd->obj.id = sou->base.unit; - cmd->obj.flags = SVGA_SCREEN_HAS_ROOT | - (sou->base.unit == 0 ? SVGA_SCREEN_IS_PRIMARY : 0); - cmd->obj.size.width = mode->hdisplay; - cmd->obj.size.height = mode->vdisplay; - cmd->obj.root.x = x; - cmd->obj.root.y = y; - - /* Ok to assume that buffer is pinned in vram */ - vmw_bo_get_guest_ptr(&sou->buffer->base, &cmd->obj.backingStore.ptr); - cmd->obj.backingStore.pitch = mode->hdisplay * 4; - - vmw_fifo_commit(dev_priv, fifo_size); - - sou->defined = true; - - return 0; -} - -/** - * Send the fifo command to destroy a screen. - */ -static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou) -{ - size_t fifo_size; - int ret; - - struct { - struct { - uint32_t cmdType; - } header; - SVGAFifoCmdDestroyScreen body; - } *cmd; - - /* no need to do anything */ - if (unlikely(!sou->defined)) - return 0; - - fifo_size = sizeof(*cmd); - cmd = vmw_fifo_reserve(dev_priv, fifo_size); - /* the hardware has hung, nothing we can do about it here */ - if (unlikely(cmd == NULL)) { - DRM_ERROR("Fifo reserve failed.\n"); - return -ENOMEM; - } - - memset(cmd, 0, fifo_size); - cmd->header.cmdType = SVGA_CMD_DESTROY_SCREEN; - cmd->body.screenId = sou->base.unit; - - vmw_fifo_commit(dev_priv, fifo_size); - - /* Force sync */ - ret = vmw_fallback_wait(dev_priv, false, true, 0, false, 3*HZ); - if (unlikely(ret != 0)) - DRM_ERROR("Failed to sync with HW"); - else - sou->defined = false; - - return ret; -} - -/** - * Free the backing store. - */ -static void vmw_sou_backing_free(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou) -{ - struct ttm_buffer_object *bo; - - if (unlikely(sou->buffer == NULL)) - return; - - bo = &sou->buffer->base; - ttm_bo_unref(&bo); - sou->buffer = NULL; - sou->buffer_size = 0; -} - -/** - * Allocate the backing store for the buffer. - */ -static int vmw_sou_backing_alloc(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou, - unsigned long size) -{ - int ret; - - if (sou->buffer_size == size) - return 0; - - if (sou->buffer) - vmw_sou_backing_free(dev_priv, sou); - - sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL); - if (unlikely(sou->buffer == NULL)) - return -ENOMEM; - - /* After we have alloced the backing store might not be able to - * resume the overlays, this is preferred to failing to alloc. - */ - vmw_overlay_pause_all(dev_priv); - ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, - &vmw_vram_ne_placement, - false, &vmw_dmabuf_bo_free); - vmw_overlay_resume_all(dev_priv); - - if (unlikely(ret != 0)) - sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ - else - sou->buffer_size = size; - - return ret; -} - -static int vmw_sou_crtc_set_config(struct drm_mode_set *set) -{ - struct vmw_private *dev_priv; - struct vmw_screen_object_unit *sou; - struct drm_connector *connector; - struct drm_display_mode *mode; - struct drm_encoder *encoder; - struct vmw_framebuffer *vfb; - struct drm_framebuffer *fb; - struct drm_crtc *crtc; - int ret = 0; - - if (!set) - return -EINVAL; - - if (!set->crtc) - return -EINVAL; - - /* get the sou */ - crtc = set->crtc; - sou = vmw_crtc_to_sou(crtc); - vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; - dev_priv = vmw_priv(crtc->dev); - - if (set->num_connectors > 1) { - DRM_ERROR("to many connectors\n"); - return -EINVAL; - } - - if (set->num_connectors == 1 && - set->connectors[0] != &sou->base.connector) { - DRM_ERROR("connector doesn't match %p %p\n", - set->connectors[0], &sou->base.connector); - return -EINVAL; - } - - /* sou only supports one fb active at the time */ - if (dev_priv->sou_priv->fb && vfb && - !(dev_priv->sou_priv->num_active == 1 && - !list_empty(&sou->active)) && - dev_priv->sou_priv->fb != vfb) { - DRM_ERROR("Multiple framebuffers not supported\n"); - return -EINVAL; - } - - /* since they always map one to one these are safe */ - connector = &sou->base.connector; - encoder = &sou->base.encoder; - - /* should we turn the crtc off */ - if (set->num_connectors == 0 || !set->mode || !set->fb) { - ret = vmw_sou_fifo_destroy(dev_priv, sou); - /* the hardware has hung don't do anything more */ - if (unlikely(ret != 0)) - return ret; - - connector->encoder = NULL; - encoder->crtc = NULL; - crtc->fb = NULL; - crtc->x = 0; - crtc->y = 0; - - vmw_sou_del_active(dev_priv, sou); - - vmw_sou_backing_free(dev_priv, sou); - - return 0; - } - - - /* we now know we want to set a mode */ - mode = set->mode; - fb = set->fb; - - if (set->x + mode->hdisplay > fb->width || - set->y + mode->vdisplay > fb->height) { - DRM_ERROR("set outside of framebuffer\n"); - return -EINVAL; - } - - vmw_fb_off(dev_priv); - - if (mode->hdisplay != crtc->mode.hdisplay || - mode->vdisplay != crtc->mode.vdisplay) { - /* no need to check if depth is different, because backing - * store depth is forced to 4 by the device. - */ - - ret = vmw_sou_fifo_destroy(dev_priv, sou); - /* the hardware has hung don't do anything more */ - if (unlikely(ret != 0)) - return ret; - - vmw_sou_backing_free(dev_priv, sou); - } - - if (!sou->buffer) { - /* forced to depth 4 by the device */ - size_t size = mode->hdisplay * mode->vdisplay * 4; - ret = vmw_sou_backing_alloc(dev_priv, sou, size); - if (unlikely(ret != 0)) - return ret; - } - - ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode); - if (unlikely(ret != 0)) { - /* - * We are in a bit of a situation here, the hardware has - * hung and we may or may not have a buffer hanging of - * the screen object, best thing to do is not do anything - * if we where defined, if not just turn the crtc of. - * Not what userspace wants but it needs to htfu. - */ - if (sou->defined) - return ret; - - connector->encoder = NULL; - encoder->crtc = NULL; - crtc->fb = NULL; - crtc->x = 0; - crtc->y = 0; - - return ret; - } - - vmw_sou_add_active(dev_priv, sou, vfb); - - connector->encoder = encoder; - encoder->crtc = crtc; - crtc->mode = *mode; - crtc->fb = fb; - crtc->x = set->x; - crtc->y = set->y; - - return 0; -} - -static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { - .save = vmw_du_crtc_save, - .restore = vmw_du_crtc_restore, - .cursor_set = vmw_du_crtc_cursor_set, - .cursor_move = vmw_du_crtc_cursor_move, - .gamma_set = vmw_du_crtc_gamma_set, - .destroy = vmw_sou_crtc_destroy, - .set_config = vmw_sou_crtc_set_config, -}; - -/* - * Screen Object Display Unit encoder functions - */ - -static void vmw_sou_encoder_destroy(struct drm_encoder *encoder) -{ - vmw_sou_destroy(vmw_encoder_to_sou(encoder)); -} - -static struct drm_encoder_funcs vmw_screen_object_encoder_funcs = { - .destroy = vmw_sou_encoder_destroy, -}; - -/* - * Screen Object Display Unit connector functions - */ - -static void vmw_sou_connector_destroy(struct drm_connector *connector) -{ - vmw_sou_destroy(vmw_connector_to_sou(connector)); -} - -static struct drm_connector_funcs vmw_legacy_connector_funcs = { - .dpms = vmw_du_connector_dpms, - .save = vmw_du_connector_save, - .restore = vmw_du_connector_restore, - .detect = vmw_du_connector_detect, - .fill_modes = vmw_du_connector_fill_modes, - .set_property = vmw_du_connector_set_property, - .destroy = vmw_sou_connector_destroy, -}; - -static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) -{ - struct vmw_screen_object_unit *sou; - struct drm_device *dev = dev_priv->dev; - struct drm_connector *connector; - struct drm_encoder *encoder; - struct drm_crtc *crtc; - - sou = kzalloc(sizeof(*sou), GFP_KERNEL); - if (!sou) - return -ENOMEM; - - sou->base.unit = unit; - crtc = &sou->base.crtc; - encoder = &sou->base.encoder; - connector = &sou->base.connector; - - INIT_LIST_HEAD(&sou->active); - - sou->base.pref_active = (unit == 0); - sou->base.pref_width = 800; - sou->base.pref_height = 600; - sou->base.pref_mode = NULL; - - drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); - connector->status = vmw_du_connector_detect(connector, true); - - drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs, - DRM_MODE_ENCODER_LVDS); - drm_mode_connector_attach_encoder(connector, encoder); - encoder->possible_crtcs = (1 << unit); - encoder->possible_clones = 0; - - drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs); - - drm_mode_crtc_set_gamma_size(crtc, 256); - - drm_connector_attach_property(connector, - dev->mode_config.dirty_info_property, - 1); - - return 0; -} - -int vmw_kms_init_screen_object_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - int i; - int ret; - - if (dev_priv->sou_priv) { - DRM_INFO("sou system already on\n"); - return -EINVAL; - } - - if (!(dev_priv->fifo.capabilities & SVGA_FIFO_CAP_SCREEN_OBJECT_2)) { - DRM_INFO("Not using screen objects," - " missing cap SCREEN_OBJECT_2\n"); - return -ENOSYS; - } - - ret = -ENOMEM; - dev_priv->sou_priv = kmalloc(sizeof(*dev_priv->sou_priv), GFP_KERNEL); - if (unlikely(!dev_priv->sou_priv)) - goto err_no_mem; - - INIT_LIST_HEAD(&dev_priv->sou_priv->active); - dev_priv->sou_priv->num_active = 0; - dev_priv->sou_priv->last_num_active = 0; - dev_priv->sou_priv->fb = NULL; - - ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); - if (unlikely(ret != 0)) - goto err_free; - - ret = drm_mode_create_dirty_info_property(dev_priv->dev); - if (unlikely(ret != 0)) - goto err_vblank_cleanup; - - for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) - vmw_sou_init(dev_priv, i); - - DRM_INFO("Screen objects system initialized\n"); - - return 0; - -err_vblank_cleanup: - drm_vblank_cleanup(dev); -err_free: - kfree(dev_priv->sou_priv); -err_no_mem: - return ret; -} - -int vmw_kms_close_screen_object_display(struct vmw_private *dev_priv) -{ - struct drm_device *dev = dev_priv->dev; - - drm_vblank_cleanup(dev); - if (!dev_priv->sou_priv) - return -ENOSYS; - - if (!list_empty(&dev_priv->sou_priv->active)) - DRM_ERROR("Still have active outputs when unloading driver"); - - kfree(dev_priv->sou_priv); - - return 0; -} diff --git a/trunk/include/drm/exynos_drm.h b/trunk/include/drm/exynos_drm.h deleted file mode 100644 index 874c4d271328..000000000000 --- a/trunk/include/drm/exynos_drm.h +++ /dev/null @@ -1,104 +0,0 @@ -/* exynos_drm.h - * - * Copyright (c) 2011 Samsung Electronics Co., Ltd. - * Authors: - * Inki Dae - * Joonyoung Shim - * Seung-Woo Kim - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef _EXYNOS_DRM_H_ -#define _EXYNOS_DRM_H_ - -/** - * User-desired buffer creation information structure. - * - * @size: requested size for the object. - * - this size value would be page-aligned internally. - * @flags: user request for setting memory type or cache attributes. - * @handle: returned handle for the object. - */ -struct drm_exynos_gem_create { - unsigned int size; - unsigned int flags; - unsigned int handle; -}; - -/** - * A structure for getting buffer offset. - * - * @handle: a pointer to gem object created. - * @pad: just padding to be 64-bit aligned. - * @offset: relatived offset value of the memory region allocated. - * - this value should be set by user. - */ -struct drm_exynos_gem_map_off { - unsigned int handle; - unsigned int pad; - uint64_t offset; -}; - -/** - * A structure for mapping buffer. - * - * @handle: a handle to gem object created. - * @size: memory size to be mapped. - * @mapped: having user virtual address mmaped. - * - this variable would be filled by exynos gem module - * of kernel side with user virtual address which is allocated - * by do_mmap(). - */ -struct drm_exynos_gem_mmap { - unsigned int handle; - unsigned int size; - uint64_t mapped; -}; - -#define DRM_EXYNOS_GEM_CREATE 0x00 -#define DRM_EXYNOS_GEM_MAP_OFFSET 0x01 -#define DRM_EXYNOS_GEM_MMAP 0x02 - -#define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create) - -#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off) - -#define DRM_IOCTL_EXYNOS_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + \ - DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap) - -/** - * Platform Specific Structure for DRM based FIMD. - * - * @timing: default video mode for initializing - * @default_win: default window layer number to be used for UI. - * @bpp: default bit per pixel. - */ -struct exynos_drm_fimd_pdata { - struct fb_videomode timing; - u32 vidcon0; - u32 vidcon1; - unsigned int default_win; - unsigned int bpp; -}; - -#endif diff --git a/trunk/include/drm/vmwgfx_drm.h b/trunk/include/drm/vmwgfx_drm.h index cd7cd8162ed6..29cd9cfdd611 100644 --- a/trunk/include/drm/vmwgfx_drm.h +++ b/trunk/include/drm/vmwgfx_drm.h @@ -52,8 +52,6 @@ #define DRM_VMW_FENCE_SIGNALED 15 #define DRM_VMW_FENCE_UNREF 16 #define DRM_VMW_FENCE_EVENT 17 -#define DRM_VMW_PRESENT 18 -#define DRM_VMW_PRESENT_READBACK 19 /*************************************************************************/ @@ -683,109 +681,5 @@ struct drm_vmw_fence_arg { }; -/*************************************************************************/ -/** - * DRM_VMW_FENCE_EVENT - * - * Queues an event on a fence to be delivered on the drm character device - * when the fence has signaled the DRM_VMW_FENCE_FLAG_EXEC flag. - * Optionally the approximate time when the fence signaled is - * given by the event. - */ - -/* - * The event type - */ -#define DRM_VMW_EVENT_FENCE_SIGNALED 0x80000000 - -struct drm_vmw_event_fence { - struct drm_event base; - uint64_t user_data; - uint32_t tv_sec; - uint32_t tv_usec; -}; - -/* - * Flags that may be given to the command. - */ -/* Request fence signaled time on the event. */ -#define DRM_VMW_FE_FLAG_REQ_TIME (1 << 0) - -/** - * struct drm_vmw_fence_event_arg - * - * @fence_rep: Pointer to fence_rep structure cast to uint64_t or 0 if - * the fence is not supposed to be referenced by user-space. - * @user_info: Info to be delivered with the event. - * @handle: Attach the event to this fence only. - * @flags: A set of flags as defined above. - */ -struct drm_vmw_fence_event_arg { - uint64_t fence_rep; - uint64_t user_data; - uint32_t handle; - uint32_t flags; -}; - -/*************************************************************************/ -/** - * DRM_VMW_PRESENT - * - * Executes an SVGA present on a given fb for a given surface. The surface - * is placed on the framebuffer. Cliprects are given relative to the given - * point (the point disignated by dest_{x|y}). - * - */ - -/** - * struct drm_vmw_present_arg - * @fb_id: framebuffer id to present / read back from. - * @sid: Surface id to present from. - * @dest_x: X placement coordinate for surface. - * @dest_y: Y placement coordinate for surface. - * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t. - * @num_clips: Number of cliprects given relative to the framebuffer origin, - * in the same coordinate space as the frame buffer. - * @pad64: Unused 64-bit padding. - * - * Input argument to the DRM_VMW_PRESENT ioctl. - */ - -struct drm_vmw_present_arg { - uint32_t fb_id; - uint32_t sid; - int32_t dest_x; - int32_t dest_y; - uint64_t clips_ptr; - uint32_t num_clips; - uint32_t pad64; -}; - - -/*************************************************************************/ -/** - * DRM_VMW_PRESENT_READBACK - * - * Executes an SVGA present readback from a given fb to the dma buffer - * currently bound as the fb. If there is no dma buffer bound to the fb, - * an error will be returned. - * - */ - -/** - * struct drm_vmw_present_arg - * @fb_id: fb_id to present / read back from. - * @num_clips: Number of cliprects. - * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t. - * @fence_rep: Pointer to a struct drm_vmw_fence_rep, cast to an uint64_t. - * If this member is NULL, then the ioctl should not return a fence. - */ - -struct drm_vmw_present_readback_arg { - uint32_t fb_id; - uint32_t num_clips; - uint64_t clips_ptr; - uint64_t fence_rep; -}; #endif