aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 16:46:44 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-25 16:46:44 -0800
commitfffddfd6c8e0c10c42c6e2cc54ba880fcc36ebbb (patch)
tree71bc5e597124dbaf7550f1e089d675718b3ed5c0 /drivers/staging
parent69086a78bdc973ec0b722be790b146e84ba8a8c4 (diff)
parentbe88298b0a3f771a4802f20c5e66af74bfd1dff1 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge from Dave Airlie: "Highlights: - TI LCD controller KMS driver - TI OMAP KMS driver merged from staging - drop gma500 stub driver - the fbcon locking fixes - the vgacon dirty like zebra fix. - open firmware videomode and hdmi common code helpers - major locking rework for kms object handling - pageflip/cursor won't block on polling anymore! - fbcon helper and prime helper cleanups - i915: all over the map, haswell power well enhancements, valleyview macro horrors cleaned up, killing lots of legacy GTT code, - radeon: CS ioctl unification, deprecated UMS support, gpu reset rework, VM fixes - nouveau: reworked thermal code, external dp/tmds encoder support (anx9805), fences sleep instead of polling, - exynos: all over the driver fixes." Lovely conflict in radeon/evergreen_cs.c between commit de0babd60d8d ("drm/radeon: enforce use of radeon_get_ib_value when reading user cmd") and the new changes that modified that evergreen_dma_cs_parse() function. * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (508 commits) drm/tilcdc: only build on arm drm/i915: Revert hdmi HDP pin checks drm/tegra: Add list of framebuffers to debugfs drm/tegra: Fix color expansion drm/tegra: Split DC_CMD_STATE_CONTROL register write drm/tegra: Implement page-flipping support drm/tegra: Implement VBLANK support drm/tegra: Implement .mode_set_base() drm/tegra: Add plane support drm/tegra: Remove bogus tegra_framebuffer structure drm: Add consistency check for page-flipping drm/radeon: Use generic HDMI infoframe helpers drm/tegra: Use generic HDMI infoframe helpers drm: Add EDID helper documentation drm: Add HDMI infoframe helpers video: Add generic HDMI infoframe helpers drm: Add some missing forward declarations drm: Move mode tables to drm_edid.c drm: Remove duplicate drm_mode_cea_vic() gma500: Fix n, m1 and m2 clock limits for sdvo and lvds ...
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/omapdrm/Kconfig25
-rw-r--r--drivers/staging/omapdrm/Makefile24
-rw-r--r--drivers/staging/omapdrm/TODO32
-rw-r--r--drivers/staging/omapdrm/omap_connector.c296
-rw-r--r--drivers/staging/omapdrm/omap_crtc.c656
-rw-r--r--drivers/staging/omapdrm/omap_debugfs.c137
-rw-r--r--drivers/staging/omapdrm/omap_dmm_priv.h188
-rw-r--r--drivers/staging/omapdrm/omap_dmm_tiler.c986
-rw-r--r--drivers/staging/omapdrm/omap_dmm_tiler.h141
-rw-r--r--drivers/staging/omapdrm/omap_drm.h123
-rw-r--r--drivers/staging/omapdrm/omap_drv.c608
-rw-r--r--drivers/staging/omapdrm/omap_drv.h333
-rw-r--r--drivers/staging/omapdrm/omap_encoder.c168
-rw-r--r--drivers/staging/omapdrm/omap_fb.c471
-rw-r--r--drivers/staging/omapdrm/omap_fbdev.c407
-rw-r--r--drivers/staging/omapdrm/omap_gem.c1507
-rw-r--r--drivers/staging/omapdrm/omap_gem_dmabuf.c225
-rw-r--r--drivers/staging/omapdrm/omap_gem_helpers.c169
-rw-r--r--drivers/staging/omapdrm/omap_irq.c322
-rw-r--r--drivers/staging/omapdrm/omap_plane.c448
-rw-r--r--drivers/staging/omapdrm/tcm-sita.c703
-rw-r--r--drivers/staging/omapdrm/tcm-sita.h95
-rw-r--r--drivers/staging/omapdrm/tcm.h328
25 files changed, 0 insertions, 8395 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 3a7965d6ac2..093f10c88cc 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -112,8 +112,6 @@ source "drivers/staging/media/Kconfig"
source "drivers/staging/net/Kconfig"
-source "drivers/staging/omapdrm/Kconfig"
-
source "drivers/staging/android/Kconfig"
source "drivers/staging/ozwpan/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 5971865d0c6..fa41b04cf4c 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_SPEAKUP) += speakup/
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_DRM_OMAP) += omapdrm/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
obj-$(CONFIG_USB_G_CCG) += ccg/
diff --git a/drivers/staging/omapdrm/Kconfig b/drivers/staging/omapdrm/Kconfig
deleted file mode 100644
index 09f65dc3d2c..00000000000
--- a/drivers/staging/omapdrm/Kconfig
+++ /dev/null
@@ -1,25 +0,0 @@
-
-config DRM_OMAP
- tristate "OMAP DRM"
- depends on DRM && !CONFIG_FB_OMAP2
- depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
- depends on OMAP2_DSS
- select DRM_KMS_HELPER
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- default n
- help
- DRM display driver for OMAP2/3/4 based boards.
-
-config DRM_OMAP_NUM_CRTCS
- int "Number of CRTCs"
- range 1 10
- default 1 if ARCH_OMAP2 || ARCH_OMAP3
- default 2 if ARCH_OMAP4
- depends on DRM_OMAP
- help
- Select the number of video overlays which can be used as framebuffers.
- The remaining overlays are reserved for video.
-
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile
deleted file mode 100644
index d85e058f284..00000000000
--- a/drivers/staging/omapdrm/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Makefile for the drm device driver. This driver provides support for the
-# Direct Rendering Infrastructure (DRI)
-#
-
-ccflags-y := -Iinclude/drm -Werror
-omapdrm-y := omap_drv.o \
- omap_irq.o \
- omap_debugfs.o \
- omap_crtc.o \
- omap_plane.o \
- omap_encoder.o \
- omap_connector.o \
- omap_fb.o \
- omap_fbdev.o \
- omap_gem.o \
- omap_gem_dmabuf.o \
- omap_dmm_tiler.o \
- tcm-sita.o
-
-# temporary:
-omapdrm-y += omap_gem_helpers.o
-
-obj-$(CONFIG_DRM_OMAP) += omapdrm.o
diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO
deleted file mode 100644
index abeeb00aaa1..00000000000
--- a/drivers/staging/omapdrm/TODO
+++ /dev/null
@@ -1,32 +0,0 @@
-TODO
-. add video decode/encode support (via syslink3 + codec-engine)
- . NOTE: with dmabuf this probably could be split into different driver
- so perhaps this TODO doesn't belong here
-. where should we do eviction (detatch_pages())? We aren't necessarily
- accessing the pages via a GART, so maybe we need some other threshold
- to put a cap on the # of pages that can be pin'd. (It is mostly only
- of interest in case you have a swap partition/file.. which a lot of
- these devices do not.. but it doesn't hurt for the driver to do the
- right thing anyways.)
- . Use mm_shrinker to trigger unpinning pages. Need to figure out how
- to handle next issue first (I think?)
- . Note TTM already has some mm_shrinker stuff.. maybe an argument to
- move to TTM? Or maybe something that could be factored out in common?
-. GEM/shmem backed pages can have existing mappings (kernel linear map,
- etc..), which isn't really ideal.
-. Revisit GEM sync object infrastructure.. TTM has some framework for this
- already. Possibly this could be refactored out and made more common?
- There should be some way to do this with less wheel-reinvention.
-. Solve PM sequencing on resume. DMM/TILER must be reloaded before any
- access is made from any component in the system. Which means on suspend
- CRTC's should be disabled, and on resume the LUT should be reprogrammed
- before CRTC's are re-enabled, to prevent DSS from trying to DMA from a
- buffer mapped in DMM/TILER before LUT is reloaded.
-
-Userspace:
-. git://github.com/robclark/xf86-video-omap.git
-
-Currently tested on
-. OMAP3530 beagleboard
-. OMAP4430 pandaboard
-. OMAP4460 pandaboard
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c
deleted file mode 100644
index 8979c80adb5..00000000000
--- a/drivers/staging/omapdrm/omap_connector.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_connector.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-/*
- * connector funcs
- */
-
-#define to_omap_connector(x) container_of(x, struct omap_connector, base)
-
-struct omap_connector {
- struct drm_connector base;
- struct omap_dss_device *dssdev;
- struct drm_encoder *encoder;
-};
-
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
- struct omap_video_timings *timings)
-{
- mode->clock = timings->pixel_clock;
-
- mode->hdisplay = timings->x_res;
- mode->hsync_start = mode->hdisplay + timings->hfp;
- mode->hsync_end = mode->hsync_start + timings->hsw;
- mode->htotal = mode->hsync_end + timings->hbp;
-
- mode->vdisplay = timings->y_res;
- mode->vsync_start = mode->vdisplay + timings->vfp;
- mode->vsync_end = mode->vsync_start + timings->vsw;
- mode->vtotal = mode->vsync_end + timings->vbp;
-
- mode->flags = 0;
-
- if (timings->interlace)
- mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
- if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- mode->flags |= DRM_MODE_FLAG_PHSYNC;
- else
- mode->flags |= DRM_MODE_FLAG_NHSYNC;
-
- if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
- mode->flags |= DRM_MODE_FLAG_PVSYNC;
- else
- mode->flags |= DRM_MODE_FLAG_NVSYNC;
-}
-
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
- struct drm_display_mode *mode)
-{
- timings->pixel_clock = mode->clock;
-
- timings->x_res = mode->hdisplay;
- timings->hfp = mode->hsync_start - mode->hdisplay;
- timings->hsw = mode->hsync_end - mode->hsync_start;
- timings->hbp = mode->htotal - mode->hsync_end;
-
- timings->y_res = mode->vdisplay;
- timings->vfp = mode->vsync_start - mode->vdisplay;
- timings->vsw = mode->vsync_end - mode->vsync_start;
- timings->vbp = mode->vtotal - mode->vsync_end;
-
- timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
-
- if (mode->flags & DRM_MODE_FLAG_PHSYNC)
- timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- else
- timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
- if (mode->flags & DRM_MODE_FLAG_PVSYNC)
- timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
- else
- timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
- timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
- timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
- timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
-}
-
-static enum drm_connector_status omap_connector_detect(
- struct drm_connector *connector, bool force)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev = omap_connector->dssdev;
- struct omap_dss_driver *dssdrv = dssdev->driver;
- enum drm_connector_status ret;
-
- if (dssdrv->detect) {
- if (dssdrv->detect(dssdev))
- ret = connector_status_connected;
- else
- ret = connector_status_disconnected;
- } else {
- ret = connector_status_unknown;
- }
-
- VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force);
-
- return ret;
-}
-
-static void omap_connector_destroy(struct drm_connector *connector)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev = omap_connector->dssdev;
-
- DBG("%s", omap_connector->dssdev->name);
- drm_sysfs_connector_remove(connector);
- drm_connector_cleanup(connector);
- kfree(omap_connector);
-
- omap_dss_put_device(dssdev);
-}
-
-#define MAX_EDID 512
-
-static int omap_connector_get_modes(struct drm_connector *connector)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev = omap_connector->dssdev;
- struct omap_dss_driver *dssdrv = dssdev->driver;
- struct drm_device *dev = connector->dev;
- int n = 0;
-
- DBG("%s", omap_connector->dssdev->name);
-
- /* if display exposes EDID, then we parse that in the normal way to
- * build table of supported modes.. otherwise (ie. fixed resolution
- * LCD panels) we just return a single mode corresponding to the
- * currently configured timings:
- */
- if (dssdrv->read_edid) {
- void *edid = kzalloc(MAX_EDID, GFP_KERNEL);
-
- if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) &&
- drm_edid_is_valid(edid)) {
- drm_mode_connector_update_edid_property(
- connector, edid);
- n = drm_add_edid_modes(connector, edid);
- } else {
- drm_mode_connector_update_edid_property(
- connector, NULL);
- }
- kfree(edid);
- } else {
- struct drm_display_mode *mode = drm_mode_create(dev);
- struct omap_video_timings timings = {0};
-
- dssdrv->get_timings(dssdev, &timings);
-
- copy_timings_omap_to_drm(mode, &timings);
-
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
- drm_mode_set_name(mode);
- drm_mode_probed_add(connector, mode);
-
- n = 1;
- }
-
- return n;
-}
-
-static int omap_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
- struct omap_dss_device *dssdev = omap_connector->dssdev;
- struct omap_dss_driver *dssdrv = dssdev->driver;
- struct omap_video_timings timings = {0};
- struct drm_device *dev = connector->dev;
- struct drm_display_mode *new_mode;
- int ret = MODE_BAD;
-
- copy_timings_drm_to_omap(&timings, mode);
- mode->vrefresh = drm_mode_vrefresh(mode);
-
- if (!dssdrv->check_timings(dssdev, &timings)) {
- /* check if vrefresh is still valid */
- new_mode = drm_mode_duplicate(dev, mode);
- new_mode->clock = timings.pixel_clock;
- new_mode->vrefresh = 0;
- if (mode->vrefresh == drm_mode_vrefresh(new_mode))
- ret = MODE_OK;
- drm_mode_destroy(dev, new_mode);
- }
-
- DBG("connector: mode %s: "
- "%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- (ret == MODE_OK) ? "valid" : "invalid",
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start,
- mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start,
- mode->vsync_end, mode->vtotal, mode->type, mode->flags);
-
- return ret;
-}
-
-struct drm_encoder *omap_connector_attached_encoder(
- struct drm_connector *connector)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
- return omap_connector->encoder;
-}
-
-static const struct drm_connector_funcs omap_connector_funcs = {
- .dpms = drm_helper_connector_dpms,
- .detect = omap_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = omap_connector_destroy,
-};
-
-static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
- .get_modes = omap_connector_get_modes,
- .mode_valid = omap_connector_mode_valid,
- .best_encoder = omap_connector_attached_encoder,
-};
-
-/* flush an area of the framebuffer (in case of manual update display that
- * is not automatically flushed)
- */
-void omap_connector_flush(struct drm_connector *connector,
- int x, int y, int w, int h)
-{
- struct omap_connector *omap_connector = to_omap_connector(connector);
-
- /* TODO: enable when supported in dss */
- VERB("%s: %d,%d, %dx%d", omap_connector->dssdev->name, x, y, w, h);
-}
-
-/* initialize connector */
-struct drm_connector *omap_connector_init(struct drm_device *dev,
- int connector_type, struct omap_dss_device *dssdev,
- struct drm_encoder *encoder)
-{
- struct drm_connector *connector = NULL;
- struct omap_connector *omap_connector;
-
- DBG("%s", dssdev->name);
-
- omap_dss_get_device(dssdev);
-
- omap_connector = kzalloc(sizeof(struct omap_connector), GFP_KERNEL);
- if (!omap_connector)
- goto fail;
-
- omap_connector->dssdev = dssdev;
- omap_connector->encoder = encoder;
-
- connector = &omap_connector->base;
-
- drm_connector_init(dev, connector, &omap_connector_funcs,
- connector_type);
- drm_connector_helper_add(connector, &omap_connector_helper_funcs);
-
-#if 0 /* enable when dss2 supports hotplug */
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD)
- connector->polled = 0;
- else
-#endif
- connector->polled = DRM_CONNECTOR_POLL_CONNECT |
- DRM_CONNECTOR_POLL_DISCONNECT;
-
- connector->interlace_allowed = 1;
- connector->doublescan_allowed = 0;
-
- drm_sysfs_connector_add(connector);
-
- return connector;
-
-fail:
- if (connector)
- omap_connector_destroy(connector);
-
- return NULL;
-}
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c
deleted file mode 100644
index 32109c09357..00000000000
--- a/drivers/staging/omapdrm/omap_crtc.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_crtc.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include <drm/drm_mode.h>
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-#define to_omap_crtc(x) container_of(x, struct omap_crtc, base)
-
-struct omap_crtc {
- struct drm_crtc base;
- struct drm_plane *plane;
-
- const char *name;
- int pipe;
- enum omap_channel channel;
- struct omap_overlay_manager_info info;
-
- /*
- * Temporary: eventually this will go away, but it is needed
- * for now to keep the output's happy. (They only need
- * mgr->id.) Eventually this will be replaced w/ something
- * more common-panel-framework-y
- */
- struct omap_overlay_manager mgr;
-
- struct omap_video_timings timings;
- bool enabled;
- bool full_update;
-
- struct omap_drm_apply apply;
-
- struct omap_drm_irq apply_irq;
- struct omap_drm_irq error_irq;
-
- /* list of in-progress apply's: */
- struct list_head pending_applies;
-
- /* list of queued apply's: */
- struct list_head queued_applies;
-
- /* for handling queued and in-progress applies: */
- struct work_struct apply_work;
-
- /* if there is a pending flip, these will be non-null: */
- struct drm_pending_vblank_event *event;
- struct drm_framebuffer *old_fb;
-
- /* for handling page flips without caring about what
- * the callback is called from. Possibly we should just
- * make omap_gem always call the cb from the worker so
- * we don't have to care about this..
- *
- * XXX maybe fold into apply_work??
- */
- struct work_struct page_flip_work;
-};
-
-/*
- * Manager-ops, callbacks from output when they need to configure
- * the upstream part of the video pipe.
- *
- * Most of these we can ignore until we add support for command-mode
- * panels.. for video-mode the crtc-helpers already do an adequate
- * job of sequencing the setup of the video pipe in the proper order
- */
-
-/* we can probably ignore these until we support command-mode panels: */
-static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
-{
-}
-
-static int omap_crtc_enable(struct omap_overlay_manager *mgr)
-{
- return 0;
-}
-
-static void omap_crtc_disable(struct omap_overlay_manager *mgr)
-{
-}
-
-static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
- const struct omap_video_timings *timings)
-{
- struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
- DBG("%s", omap_crtc->name);
- omap_crtc->timings = *timings;
- omap_crtc->full_update = true;
-}
-
-static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr,
- const struct dss_lcd_mgr_config *config)
-{
- struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
- DBG("%s", omap_crtc->name);
- dispc_mgr_set_lcd_config(omap_crtc->channel, config);
-}
-
-static int omap_crtc_register_framedone_handler(
- struct omap_overlay_manager *mgr,
- void (*handler)(void *), void *data)
-{
- return 0;
-}
-
-static void omap_crtc_unregister_framedone_handler(
- struct omap_overlay_manager *mgr,
- void (*handler)(void *), void *data)
-{
-}
-
-static const struct dss_mgr_ops mgr_ops = {
- .start_update = omap_crtc_start_update,
- .enable = omap_crtc_enable,
- .disable = omap_crtc_disable,
- .set_timings = omap_crtc_set_timings,
- .set_lcd_config = omap_crtc_set_lcd_config,
- .register_framedone_handler = omap_crtc_register_framedone_handler,
- .unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
-};
-
-/*
- * CRTC funcs:
- */
-
-static void omap_crtc_destroy(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-
- DBG("%s", omap_crtc->name);
-
- WARN_ON(omap_crtc->apply_irq.registered);
- omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
-
- omap_crtc->plane->funcs->destroy(omap_crtc->plane);
- drm_crtc_cleanup(crtc);
-
- kfree(omap_crtc);
-}
-
-static void omap_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
- struct omap_drm_private *priv = crtc->dev->dev_private;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- bool enabled = (mode == DRM_MODE_DPMS_ON);
- int i;
-
- DBG("%s: %d", omap_crtc->name, mode);
-
- if (enabled != omap_crtc->enabled) {
- omap_crtc->enabled = enabled;
- omap_crtc->full_update = true;
- omap_crtc_apply(crtc, &omap_crtc->apply);
-
- /* also enable our private plane: */
- WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
-
- /* and any attached overlay planes: */
- for (i = 0; i < priv->num_planes; i++) {
- struct drm_plane *plane = priv->planes[i];
- if (plane->crtc == crtc)
- WARN_ON(omap_plane_dpms(plane, mode));
- }
- }
-}
-
-static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static int omap_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)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-
- mode = adjusted_mode;
-
- DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
- omap_crtc->name, mode->base.id, mode->name,
- mode->vrefresh, mode->clock,
- mode->hdisplay, mode->hsync_start,
- mode->hsync_end, mode->htotal,
- mode->vdisplay, mode->vsync_start,
- mode->vsync_end, mode->vtotal,
- mode->type, mode->flags);
-
- copy_timings_drm_to_omap(&omap_crtc->timings, mode);
- omap_crtc->full_update = true;
-
- return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
- 0, 0, mode->hdisplay, mode->vdisplay,
- x << 16, y << 16,
- mode->hdisplay << 16, mode->vdisplay << 16,
- NULL, NULL);
-}
-
-static void omap_crtc_prepare(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->name);
- omap_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
-static void omap_crtc_commit(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- DBG("%s", omap_crtc->name);
- omap_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-}
-
-static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct drm_plane *plane = omap_crtc->plane;
- struct drm_display_mode *mode = &crtc->mode;
-
- return omap_plane_mode_set(plane, crtc, crtc->fb,
- 0, 0, mode->hdisplay, mode->vdisplay,
- x << 16, y << 16,
- mode->hdisplay << 16, mode->vdisplay << 16,
- NULL, NULL);
-}
-
-static void omap_crtc_load_lut(struct drm_crtc *crtc)
-{
-}
-
-static void vblank_cb(void *arg)
-{
- struct drm_crtc *crtc = arg;
- struct drm_device *dev = crtc->dev;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- unsigned long flags;
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- /* wakeup userspace */
- if (omap_crtc->event)
- drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event);
-
- omap_crtc->event = NULL;
- omap_crtc->old_fb = NULL;
-
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
-static void page_flip_worker(struct work_struct *work)
-{
- struct omap_crtc *omap_crtc =
- container_of(work, struct omap_crtc, page_flip_work);
- struct drm_crtc *crtc = &omap_crtc->base;
- struct drm_device *dev = crtc->dev;
- struct drm_display_mode *mode = &crtc->mode;
- struct drm_gem_object *bo;
-
- mutex_lock(&dev->mode_config.mutex);
- omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
- 0, 0, mode->hdisplay, mode->vdisplay,
- crtc->x << 16, crtc->y << 16,
- mode->hdisplay << 16, mode->vdisplay << 16,
- vblank_cb, crtc);
- mutex_unlock(&dev->mode_config.mutex);
-
- bo = omap_framebuffer_bo(crtc->fb, 0);
- drm_gem_object_unreference_unlocked(bo);
-}
-
-static void page_flip_cb(void *arg)
-{
- struct drm_crtc *crtc = arg;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct omap_drm_private *priv = crtc->dev->dev_private;
-
- /* avoid assumptions about what ctxt we are called from: */
- queue_work(priv->wq, &omap_crtc->page_flip_work);
-}
-
-static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
- struct drm_pending_vblank_event *event)
-{
- struct drm_device *dev = crtc->dev;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct drm_gem_object *bo;
-
- DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1,
- fb->base.id, event);
-
- if (omap_crtc->old_fb) {
- dev_err(dev->dev, "already a pending flip\n");
- return -EINVAL;
- }
-
- omap_crtc->event = event;
- crtc->fb = fb;
-
- /*
- * Hold a reference temporarily until the crtc is updated
- * and takes the reference to the bo. This avoids it
- * getting freed from under us:
- */
- bo = omap_framebuffer_bo(fb, 0);
- drm_gem_object_reference(bo);
-
- omap_gem_op_async(bo, OMAP_GEM_READ, page_flip_cb, crtc);
-
- return 0;
-}
-
-static int omap_crtc_set_property(struct drm_crtc *crtc,
- struct drm_property *property, uint64_t val)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct omap_drm_private *priv = crtc->dev->dev_private;
-
- if (property == priv->rotation_prop) {
- crtc->invert_dimensions =
- !!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
- }
-
- return omap_plane_set_property(omap_crtc->plane, property, val);
-}
-
-static const struct drm_crtc_funcs omap_crtc_funcs = {
- .set_config = drm_crtc_helper_set_config,
- .destroy = omap_crtc_destroy,
- .page_flip = omap_crtc_page_flip_locked,
- .set_property = omap_crtc_set_property,
-};
-
-static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
- .dpms = omap_crtc_dpms,
- .mode_fixup = omap_crtc_mode_fixup,
- .mode_set = omap_crtc_mode_set,
- .prepare = omap_crtc_prepare,
- .commit = omap_crtc_commit,
- .mode_set_base = omap_crtc_mode_set_base,
- .load_lut = omap_crtc_load_lut,
-};
-
-const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- return &omap_crtc->timings;
-}
-
-enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- return omap_crtc->channel;
-}
-
-static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
- struct omap_crtc *omap_crtc =
- container_of(irq, struct omap_crtc, error_irq);
- struct drm_crtc *crtc = &omap_crtc->base;
- DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
- /* avoid getting in a flood, unregister the irq until next vblank */
- omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
-}
-
-static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
- struct omap_crtc *omap_crtc =
- container_of(irq, struct omap_crtc, apply_irq);
- struct drm_crtc *crtc = &omap_crtc->base;
-
- if (!omap_crtc->error_irq.registered)
- omap_irq_register(crtc->dev, &omap_crtc->error_irq);
-
- if (!dispc_mgr_go_busy(omap_crtc->channel)) {
- struct omap_drm_private *priv =
- crtc->dev->dev_private;
- DBG("%s: apply done", omap_crtc->name);
- omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
- queue_work(priv->wq, &omap_crtc->apply_work);
- }
-}
-
-static void apply_worker(struct work_struct *work)
-{
- struct omap_crtc *omap_crtc =
- container_of(work, struct omap_crtc, apply_work);
- struct drm_crtc *crtc = &omap_crtc->base;
- struct drm_device *dev = crtc->dev;
- struct omap_drm_apply *apply, *n;
- bool need_apply;
-
- /*
- * Synchronize everything on mode_config.mutex, to keep
- * the callbacks and list modification all serialized
- * with respect to modesetting ioctls from userspace.
- */
- mutex_lock(&dev->mode_config.mutex);
- dispc_runtime_get();
-
- /*
- * If we are still pending a previous update, wait.. when the
- * pending update completes, we get kicked again.
- */
- if (omap_crtc->apply_irq.registered)
- goto out;
-
- /* finish up previous apply's: */
- list_for_each_entry_safe(apply, n,
- &omap_crtc->pending_applies, pending_node) {
- apply->post_apply(apply);
- list_del(&apply->pending_node);
- }
-
- need_apply = !list_empty(&omap_crtc->queued_applies);
-
- /* then handle the next round of of queued apply's: */
- list_for_each_entry_safe(apply, n,
- &omap_crtc->queued_applies, queued_node) {
- apply->pre_apply(apply);
- list_del(&apply->queued_node);
- apply->queued = false;
- list_add_tail(&apply->pending_node,
- &omap_crtc->pending_applies);
- }
-
- if (need_apply) {
- enum omap_channel channel = omap_crtc->channel;
-
- DBG("%s: GO", omap_crtc->name);
-
- if (dispc_mgr_is_enabled(channel)) {
- omap_irq_register(dev, &omap_crtc->apply_irq);
- dispc_mgr_go(channel);
- } else {
- struct omap_drm_private *priv = dev->dev_private;
- queue_work(priv->wq, &omap_crtc->apply_work);
- }
- }
-
-out:
- dispc_runtime_put();
- mutex_unlock(&dev->mode_config.mutex);
-}
-
-int omap_crtc_apply(struct drm_crtc *crtc,
- struct omap_drm_apply *apply)
-{
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- struct drm_device *dev = crtc->dev;
-
- WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
-
- /* no need to queue it again if it is already queued: */
- if (apply->queued)
- return 0;
-
- apply->queued = true;
- list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
-
- /*
- * If there are no currently pending updates, then go ahead and
- * kick the worker immediately, otherwise it will run again when
- * the current update finishes.
- */
- if (list_empty(&omap_crtc->pending_applies)) {
- struct omap_drm_private *priv = crtc->dev->dev_private;
- queue_work(priv->wq, &omap_crtc->apply_work);
- }
-
- return 0;
-}
-
-/* called only from apply */
-static void set_enabled(struct drm_crtc *crtc, bool enable)
-{
- struct drm_device *dev = crtc->dev;
- struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- enum omap_channel channel = omap_crtc->channel;
- struct omap_irq_wait *wait = NULL;
-
- if (dispc_mgr_is_enabled(channel) == enable)
- return;
-
- /* ignore sync-lost irqs during enable/disable */
- omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
-
- if (dispc_mgr_get_framedone_irq(channel)) {
- if (!enable) {
- wait = omap_irq_wait_init(dev,
- dispc_mgr_get_framedone_irq(channel), 1);
- }
- } else {
- /*
- * When we disable digit output, we need to wait until fields
- * are done. Otherwise the DSS is still working, and turning
- * off the clocks prevents DSS from going to OFF mode. And when
- * enabling, we need to wait for the extra sync losts
- */
- wait = omap_irq_wait_init(dev,
- dispc_mgr_get_vsync_irq(channel), 2);
- }
-
- dispc_mgr_enable(channel, enable);
-
- if (wait) {
- int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
- if (ret) {
- dev_err(dev->dev, "%s: timeout waiting for %s\n",
- omap_crtc->name, enable ? "enable" : "disable");
- }
- }
-
- omap_irq_register(crtc->dev, &omap_crtc->error_irq);
-}
-
-static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
-{
- struct omap_crtc *omap_crtc =
- container_of(apply, struct omap_crtc, apply);
- struct drm_crtc *crtc = &omap_crtc->base;
- struct drm_encoder *encoder = NULL;
-
- DBG("%s: enabled=%d, full=%d", omap_crtc->name,
- omap_crtc->enabled, omap_crtc->full_update);
-
- if (omap_crtc->full_update) {
- struct omap_drm_private *priv = crtc->dev->dev_private;
- int i;
- for (i = 0; i < priv->num_encoders; i++) {
- if (priv->encoders[i]->crtc == crtc) {
- encoder = priv->encoders[i];
- break;
- }
- }
- }
-
- if (!omap_crtc->enabled) {
- set_enabled(&omap_crtc->base, false);
- if (encoder)
- omap_encoder_set_enabled(encoder, false);
- } else {
- if (encoder) {
- omap_encoder_set_enabled(encoder, false);
- omap_encoder_update(encoder, &omap_crtc->mgr,
- &omap_crtc->timings);
- omap_encoder_set_enabled(encoder, true);
- omap_crtc->full_update = false;
- }
-
- dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
- dispc_mgr_set_timings(omap_crtc->channel,
- &omap_crtc->timings);
- set_enabled(&omap_crtc->base, true);
- }
-
- omap_crtc->full_update = false;
-}
-
-static void omap_crtc_post_apply(struct omap_drm_apply *apply)
-{
- /* nothing needed for post-apply */
-}
-
-static const char *channel_names[] = {
- [OMAP_DSS_CHANNEL_LCD] = "lcd",
- [OMAP_DSS_CHANNEL_DIGIT] = "tv",
- [OMAP_DSS_CHANNEL_LCD2] = "lcd2",
-};
-
-/* initialize crtc */
-struct drm_crtc *omap_crtc_init(struct drm_device *dev,
- struct drm_plane *plane, enum omap_channel channel, int id)
-{
- struct drm_crtc *crtc = NULL;
- struct omap_crtc *omap_crtc;
- struct omap_overlay_manager_info *info;
-
- DBG("%s", channel_names[channel]);
-
- omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
- if (!omap_crtc)
- goto fail;
-
- crtc = &omap_crtc->base;
-
- INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker);
- INIT_WORK(&omap_crtc->apply_work, apply_worker);
-
- INIT_LIST_HEAD(&omap_crtc->pending_applies);
- INIT_LIST_HEAD(&omap_crtc->queued_applies);
-
- omap_crtc->apply.pre_apply = omap_crtc_pre_apply;
- omap_crtc->apply.post_apply = omap_crtc_post_apply;
-
- omap_crtc->apply_irq.irqmask = pipe2vbl(id);
- omap_crtc->apply_irq.irq = omap_crtc_apply_irq;
-
- omap_crtc->error_irq.irqmask =
- dispc_mgr_get_sync_lost_irq(channel);
- omap_crtc->error_irq.irq = omap_crtc_error_irq;
- omap_irq_register(dev, &omap_crtc->error_irq);
-
- omap_crtc->channel = channel;
- omap_crtc->plane = plane;
- omap_crtc->plane->crtc = crtc;
- omap_crtc->name = channel_names[channel];
- omap_crtc->pipe = id;
-
- /* temporary: */
- omap_crtc->mgr.id = channel;
-
- dss_install_mgr_ops(&mgr_ops);
-
- /* TODO: fix hard-coded setup.. add properties! */
- info = &omap_crtc->info;
- info->default_color = 0x00000000;
- info->trans_key = 0x00000000;
- info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
- info->trans_enabled = false;
-
- drm_crtc_init(dev, crtc, &omap_crtc_funcs);
- drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
-
- omap_plane_install_properties(omap_crtc->plane, &crtc->base);
-
- return crtc;
-
-fail:
- if (crtc)
- omap_crtc_destroy(crtc);
-
- return NULL;
-}
diff --git a/drivers/staging/omapdrm/omap_debugfs.c b/drivers/staging/omapdrm/omap_debugfs.c
deleted file mode 100644
index 2f122e00b51..00000000000
--- a/drivers/staging/omapdrm/omap_debugfs.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_debugfs.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-#include "omap_dmm_tiler.h"
-
-#include "drm_fb_helper.h"
-
-
-#ifdef CONFIG_DEBUG_FS
-
-static int gem_show(struct seq_file *m, void *arg)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct omap_drm_private *priv = dev->dev_private;
- int ret;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret)
- return ret;
-
- seq_printf(m, "All Objects:\n");
- omap_gem_describe_objects(&priv->obj_list, m);
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-}
-
-static int mm_show(struct seq_file *m, void *arg)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- return drm_mm_dump_table(m, dev->mm_private);
-}
-
-static int fb_show(struct seq_file *m, void *arg)
-{
- struct drm_info_node *node = (struct drm_info_node *) m->private;
- struct drm_device *dev = node->minor->dev;
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_framebuffer *fb;
- int ret;
-
- ret = mutex_lock_interruptible(&dev->mode_config.mutex);
- if (ret)
- return ret;
-
- ret = mutex_lock_interruptible(&dev->struct_mutex);
- if (ret) {
- mutex_unlock(&dev->mode_config.mutex);
- return ret;
- }
-
- seq_printf(m, "fbcon ");
- omap_framebuffer_describe(priv->fbdev->fb, m);
-
- list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
- if (fb == priv->fbdev->fb)
- continue;
-
- seq_printf(m, "user ");
- omap_framebuffer_describe(fb, m);
- }
-
- mutex_unlock(&dev->struct_mutex);
- mutex_unlock(&dev->mode_config.mutex);
-
- return 0;
-}
-
-/* list of debufs files that are applicable to all devices */
-static struct drm_info_list omap_debugfs_list[] = {
- {"gem", gem_show, 0},
- {"mm", mm_show, 0},
- {"fb", fb_show, 0},
-};
-
-/* list of debugfs files that are specific to devices with dmm/tiler */
-static struct drm_info_list omap_dmm_debugfs_list[] = {
- {"tiler_map", tiler_map_show, 0},
-};
-
-int omap_debugfs_init(struct drm_minor *minor)
-{
- struct drm_device *dev = minor->dev;
- int ret;
-
- ret = drm_debugfs_create_files(omap_debugfs_list,
- ARRAY_SIZE(omap_debugfs_list),
- minor->debugfs_root, minor);
-
- if (ret) {
- dev_err(dev->dev, "could not install omap_debugfs_list\n");
- return ret;
- }
-
- if (dmm_is_available())
- ret = drm_debugfs_create_files(omap_dmm_debugfs_list,
- ARRAY_SIZE(omap_dmm_debugfs_list),
- minor->debugfs_root, minor);
-
- if (ret) {
- dev_err(dev->dev, "could not install omap_dmm_debugfs_list\n");
- return ret;
- }
-
- return ret;
-}
-
-void omap_debugfs_cleanup(struct drm_minor *minor)
-{
- drm_debugfs_remove_files(omap_debugfs_list,
- ARRAY_SIZE(omap_debugfs_list), minor);
- if (dmm_is_available())
- drm_debugfs_remove_files(omap_dmm_debugfs_list,
- ARRAY_SIZE(omap_dmm_debugfs_list), minor);
-}
-
-#endif
diff --git a/drivers/staging/omapdrm/omap_dmm_priv.h b/drivers/staging/omapdrm/omap_dmm_priv.h
deleted file mode 100644
index 58bcd6ae025..00000000000
--- a/drivers/staging/omapdrm/omap_dmm_priv.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Rob Clark <rob@ti.com>
- * Andy Gross <andy.gross@ti.com>
- *
- * 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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifndef OMAP_DMM_PRIV_H
-#define OMAP_DMM_PRIV_H
-
-#define DMM_REVISION 0x000
-#define DMM_HWINFO 0x004
-#define DMM_LISA_HWINFO 0x008
-#define DMM_DMM_SYSCONFIG 0x010
-#define DMM_LISA_LOCK 0x01C
-#define DMM_LISA_MAP__0 0x040
-#define DMM_LISA_MAP__1 0x044
-#define DMM_TILER_HWINFO 0x208
-#define DMM_TILER_OR__0 0x220
-#define DMM_TILER_OR__1 0x224
-#define DMM_PAT_HWINFO 0x408
-#define DMM_PAT_GEOMETRY 0x40C
-#define DMM_PAT_CONFIG 0x410
-#define DMM_PAT_VIEW__0 0x420
-#define DMM_PAT_VIEW__1 0x424
-#define DMM_PAT_VIEW_MAP__0 0x440
-#define DMM_PAT_VIEW_MAP_BASE 0x460
-#define DMM_PAT_IRQ_EOI 0x478
-#define DMM_PAT_IRQSTATUS_RAW 0x480
-#define DMM_PAT_IRQSTATUS 0x490
-#define DMM_PAT_IRQENABLE_SET 0x4A0
-#define DMM_PAT_IRQENABLE_CLR 0x4B0
-#define DMM_PAT_STATUS__0 0x4C0
-#define DMM_PAT_STATUS__1 0x4C4
-#define DMM_PAT_STATUS__2 0x4C8
-#define DMM_PAT_STATUS__3 0x4CC
-#define DMM_PAT_DESCR__0 0x500
-#define DMM_PAT_DESCR__1 0x510
-#define DMM_PAT_DESCR__2 0x520
-#define DMM_PAT_DESCR__3 0x530
-#define DMM_PEG_HWINFO 0x608
-#define DMM_PEG_PRIO 0x620
-#define DMM_PEG_PRIO_PAT 0x640
-
-#define DMM_IRQSTAT_DST (1<<0)
-#define DMM_IRQSTAT_LST (1<<1)
-#define DMM_IRQSTAT_ERR_INV_DSC (1<<2)
-#define DMM_IRQSTAT_ERR_INV_DATA (1<<3)
-#define DMM_IRQSTAT_ERR_UPD_AREA (1<<4)
-#define DMM_IRQSTAT_ERR_UPD_CTRL (1<<5)
-#define DMM_IRQSTAT_ERR_UPD_DATA (1<<6)
-#define DMM_IRQSTAT_ERR_LUT_MISS (1<<7)
-
-#define DMM_IRQSTAT_ERR_MASK (DMM_IRQ_STAT_ERR_INV_DSC | \
- DMM_IRQ_STAT_ERR_INV_DATA | \
- DMM_IRQ_STAT_ERR_UPD_AREA | \
- DMM_IRQ_STAT_ERR_UPD_CTRL | \
- DMM_IRQ_STAT_ERR_UPD_DATA | \
- DMM_IRQ_STAT_ERR_LUT_MISS)
-
-#define DMM_PATSTATUS_READY (1<<0)
-#define DMM_PATSTATUS_VALID (1<<1)
-#define DMM_PATSTATUS_RUN (1<<2)
-#define DMM_PATSTATUS_DONE (1<<3)
-#define DMM_PATSTATUS_LINKED (1<<4)
-#define DMM_PATSTATUS_BYPASSED (1<<7)
-#define DMM_PATSTATUS_ERR_INV_DESCR (1<<10)
-#define DMM_PATSTATUS_ERR_INV_DATA (1<<11)
-#define DMM_PATSTATUS_ERR_UPD_AREA (1<<12)
-#define DMM_PATSTATUS_ERR_UPD_CTRL (1<<13)
-#define DMM_PATSTATUS_ERR_UPD_DATA (1<<14)
-#define DMM_PATSTATUS_ERR_ACCESS (1<<15)
-
-/* note: don't treat DMM_PATSTATUS_ERR_ACCESS as an error */
-#define DMM_PATSTATUS_ERR (DMM_PATSTATUS_ERR_INV_DESCR | \
- DMM_PATSTATUS_ERR_INV_DATA | \
- DMM_PATSTATUS_ERR_UPD_AREA | \
- DMM_PATSTATUS_ERR_UPD_CTRL | \
- DMM_PATSTATUS_ERR_UPD_DATA)
-
-
-
-enum {
- PAT_STATUS,
- PAT_DESCR
-};
-
-struct pat_ctrl {
- u32 start:4;
- u32 dir:4;
- u32 lut_id:8;
- u32 sync:12;
- u32 ini:4;
-};
-
-struct pat {
- uint32_t next_pa;
- struct pat_area area;
- struct pat_ctrl ctrl;
- uint32_t data_pa;
-};
-
-#define DMM_FIXED_RETRY_COUNT 1000
-
-/* create refill buffer big enough to refill all slots, plus 3 descriptors..
- * 3 descriptors is probably the worst-case for # of 2d-slices in a 1d area,
- * but I guess you don't hit that worst case at the same time as full area
- * refill
- */
-#define DESCR_SIZE 128
-#define REFILL_BUFFER_SIZE ((4 * 128 * 256) + (3 * DESCR_SIZE))
-
-/* For OMAP5, a fixed offset is added to all Y coordinates for 1D buffers.
- * This is used in programming to address the upper portion of the LUT
-*/
-#define OMAP5_LUT_OFFSET 128
-
-struct dmm;
-
-struct dmm_txn {
- void *engine_handle;
- struct tcm *tcm;
-
- uint8_t *current_va;
- dma_addr_t current_pa;
-
- struct pat *last_pat;
-};
-
-struct refill_engine {
- int id;
- struct dmm *dmm;
- struct tcm *tcm;
-
- uint8_t *refill_va;
- dma_addr_t refill_pa;
-
- /* only one trans per engine for now */
- struct dmm_txn txn;
-
- bool async;
-
- wait_queue_head_t wait_for_refill;
-
- struct list_head idle_node;
-};
-
-struct dmm {
- struct device *dev;
- void __iomem *base;
- int irq;
-
- struct page *dummy_page;
- dma_addr_t dummy_pa;
-
- void *refill_va;
- dma_addr_t refill_pa;
-
- /* refill engines */
- wait_queue_head_t engine_queue;
- struct list_head idle_head;
- struct refill_engine *engines;
- int num_engines;
- atomic_t engine_counter;
-
- /* container information */
- int container_width;
- int container_height;
- int lut_width;
- int lut_height;
- int num_lut;
-
- /* array of LUT - TCM containers */
- struct tcm **tcm;
-
- /* allocation list and lock */
- struct list_head alloc_head;
-};
-
-#endif
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.c b/drivers/staging/omapdrm/omap_dmm_tiler.c
deleted file mode 100644
index 9b794c933c8..00000000000
--- a/drivers/staging/omapdrm/omap_dmm_tiler.c
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * DMM IOMMU driver support functions for TI OMAP processors.
- *
- * Author: Rob Clark <rob@ti.com>
- * Andy Gross <andy.gross@ti.com>
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * 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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h> /* platform_device() */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/interrupt.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/time.h>
-#include <linux/list.h>
-
-#include "omap_dmm_tiler.h"
-#include "omap_dmm_priv.h"
-
-#define DMM_DRIVER_NAME "dmm"
-
-/* mappings for associating views to luts */
-static struct tcm *containers[TILFMT_NFORMATS];
-static struct dmm *omap_dmm;
-
-/* global spinlock for protecting lists */
-static DEFINE_SPINLOCK(list_lock);
-
-/* Geometry table */
-#define GEOM(xshift, yshift, bytes_per_pixel) { \
- .x_shft = (xshift), \
- .y_shft = (yshift), \
- .cpp = (bytes_per_pixel), \
- .slot_w = 1 << (SLOT_WIDTH_BITS - (xshift)), \
- .slot_h = 1 << (SLOT_HEIGHT_BITS - (yshift)), \
- }
-
-static const struct {
- uint32_t x_shft; /* unused X-bits (as part of bpp) */
- uint32_t y_shft; /* unused Y-bits (as part of bpp) */
- uint32_t cpp; /* bytes/chars per pixel */
- uint32_t slot_w; /* width of each slot (in pixels) */
- uint32_t slot_h; /* height of each slot (in pixels) */
-} geom[TILFMT_NFORMATS] = {
- [TILFMT_8BIT] = GEOM(0, 0, 1),
- [TILFMT_16BIT] = GEOM(0, 1, 2),
- [TILFMT_32BIT] = GEOM(1, 1, 4),
- [TILFMT_PAGE] = GEOM(SLOT_WIDTH_BITS, SLOT_HEIGHT_BITS, 1),
-};
-
-
-/* lookup table for registers w/ per-engine instances */
-static const uint32_t reg[][4] = {
- [PAT_STATUS] = {DMM_PAT_STATUS__0, DMM_PAT_STATUS__1,
- DMM_PAT_STATUS__2, DMM_PAT_STATUS__3},
- [PAT_DESCR] = {DMM_PAT_DESCR__0, DMM_PAT_DESCR__1,
- DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
-};
-
-/* simple allocator to grab next 16 byte aligned memory from txn */
-static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
-{
- void *ptr;
- struct refill_engine *engine = txn->engine_handle;
-
- /* dmm programming requires 16 byte aligned addresses */
- txn->current_pa = round_up(txn->current_pa, 16);
- txn->current_va = (void *)round_up((long)txn->current_va, 16);
-
- ptr = txn->current_va;
- *pa = txn->current_pa;
-
- txn->current_pa += sz;
- txn->current_va += sz;
-
- BUG_ON((txn->current_va - engine->refill_va) > REFILL_BUFFER_SIZE);
-
- return ptr;
-}
-
-/* check status and spin until wait_mask comes true */
-static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
-{
- struct dmm *dmm = engine->dmm;
- uint32_t r = 0, err, i;
-
- i = DMM_FIXED_RETRY_COUNT;
- while (true) {
- r = readl(dmm->base + reg[PAT_STATUS][engine->id]);
- err = r & DMM_PATSTATUS_ERR;
- if (err)
- return -EFAULT;
-
- if ((r & wait_mask) == wait_mask)
- break;
-
- if (--i == 0)
- return -ETIMEDOUT;
-
- udelay(1);
- }
-
- return 0;
-}
-
-static void release_engine(struct refill_engine *engine)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&list_lock, flags);
- list_add(&engine->idle_node, &omap_dmm->idle_head);
- spin_unlock_irqrestore(&list_lock, flags);
-
- atomic_inc(&omap_dmm->engine_counter);
- wake_up_interruptible(&omap_dmm->engine_queue);
-}
-
-static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
-{
- struct dmm *dmm = arg;
- uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS);
- int i;
-
- /* ack IRQ */
- writel(status, dmm->base + DMM_PAT_IRQSTATUS);
-
- for (i = 0; i < dmm->num_engines; i++) {
- if (status & DMM_IRQSTAT_LST) {
- wake_up_interruptible(&dmm->engines[i].wait_for_refill);
-
- if (dmm->engines[i].async)
- release_engine(&dmm->engines[i]);
- }
-
- status >>= 8;
- }
-
- return IRQ_HANDLED;
-}
-
-/**
- * Get a handle for a DMM transaction
- */
-static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
-{
- struct dmm_txn *txn = NULL;
- struct refill_engine *engine = NULL;
- int ret;
- unsigned long flags;
-
-
- /* wait until an engine is available */
- ret = wait_event_interruptible(omap_dmm->engine_queue,
- atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
- if (ret)
- return ERR_PTR(ret);
-
- /* grab an idle engine */
- spin_lock_irqsave(&list_lock, flags);
- if (!list_empty(&dmm->idle_head)) {
- engine = list_entry(dmm->idle_head.next, struct refill_engine,
- idle_node);
- list_del(&engine->idle_node);
- }
- spin_unlock_irqrestore(&list_lock, flags);
-
- BUG_ON(!engine);
-
- txn = &engine->txn;
- engine->tcm = tcm;
- txn->engine_handle = engine;
- txn->last_pat = NULL;
- txn->current_va = engine->refill_va;
- txn->current_pa = engine->refill_pa;
-
- return txn;
-}
-
-/**
- * Add region to DMM transaction. If pages or pages[i] is NULL, then the
- * corresponding slot is cleared (ie. dummy_pa is programmed)
- */
-static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
- struct page **pages, uint32_t npages, uint32_t roll)
-{
- dma_addr_t pat_pa = 0;
- uint32_t *data;
- struct pat *pat;
- struct refill_engine *engine = txn->engine_handle;
- int columns = (1 + area->x1 - area->x0);
- int rows = (1 + area->y1 - area->y0);
- int i = columns*rows;
-
- pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
-
- if (txn->last_pat)
- txn->last_pat->next_pa = (uint32_t)pat_pa;
-
- pat->area = *area;
-
- /* adjust Y coordinates based off of container parameters */
- pat->area.y0 += engine->tcm->y_offset;
- pat->area.y1 += engine->tcm->y_offset;
-
- pat->ctrl = (struct pat_ctrl){
- .start = 1,
- .lut_id = engine->tcm->lut_id,
- };
-
- data = alloc_dma(txn, 4*i, &pat->data_pa);
-
- while (i--) {
- int n = i + roll;
- if (n >= npages)
- n -= npages;
- data[i] = (pages && pages[n]) ?
- page_to_phys(pages[n]) : engine->dmm->dummy_pa;
- }
-
- txn->last_pat = pat;
-
- return;
-}
-
-/**
- * Commit the DMM transaction.
- */
-static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
-{
- int ret = 0;
- struct refill_engine *engine = txn->engine_handle;
- struct dmm *dmm = engine->dmm;
-
- if (!txn->last_pat) {
- dev_err(engine->dmm->dev, "need at least one txn\n");
- ret = -EINVAL;
- goto cleanup;
- }
-
- txn->last_pat->next_pa = 0;
-
- /* write to PAT_DESCR to clear out any pending transaction */
- writel(0x0, dmm->base + reg[PAT_DESCR][engine->id]);
-
- /* wait for engine ready: */
- ret = wait_status(engine, DMM_PATSTATUS_READY);
- if (ret) {
- ret = -EFAULT;
- goto cleanup;
- }
-
- /* mark whether it is async to denote list management in IRQ handler */
- engine->async = wait ? false : true;
-
- /* kick reload */
- writel(engine->refill_pa,
- dmm->base + reg[PAT_DESCR][engine->id]);
-
- if (wait) {
- if (wait_event_interruptible_timeout(engine->wait_for_refill,
- wait_status(engine, DMM_PATSTATUS_READY) == 0,
- msecs_to_jiffies(1)) <= 0) {
- dev_err(dmm->dev, "timed out waiting for done\n");
- ret = -ETIMEDOUT;
- }
- }
-
-cleanup:
- /* only place engine back on list if we are done with it */
- if (ret || wait)
- release_engine(engine);
-
- return ret;
-}
-
-/*
- * DMM programming
- */
-static int fill(struct tcm_area *area, struct page **pages,
- uint32_t npages, uint32_t roll, bool wait)
-{
- int ret = 0;
- struct tcm_area slice, area_s;
- struct dmm_txn *txn;
-
- txn = dmm_txn_init(omap_dmm, area->tcm);
- if (IS_ERR_OR_NULL(txn))
- return -ENOMEM;
-
- tcm_for_each_slice(slice, *area, area_s) {
- struct pat_area p_area = {
- .x0 = slice.p0.x, .y0 = slice.p0.y,
- .x1 = slice.p1.x, .y1 = slice.p1.y,
- };
-
- dmm_txn_append(txn, &p_area, pages, npages, roll);
-
- roll += tcm_sizeof(slice);
- }
-
- ret = dmm_txn_commit(txn, wait);
-
- return ret;
-}
-
-/*
- * Pin/unpin
- */
-
-/* note: slots for which pages[i] == NULL are filled w/ dummy page
- */
-int tiler_pin(struct tiler_block *block, struct page **pages,
- uint32_t npages, uint32_t roll, bool wait)
-{
- int ret;
-
- ret = fill(&block->area, pages, npages, roll, wait);
-
- if (ret)
- tiler_unpin(block);
-
- return ret;
-}
-
-int tiler_unpin(struct tiler_block *block)
-{
- return fill(&block->area, NULL, 0, 0, false);
-}
-
-/*
- * Reserve/release
- */
-struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
- uint16_t h, uint16_t align)
-{
- struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
- u32 min_align = 128;
- int ret;
- unsigned long flags;
-
- BUG_ON(!validfmt(fmt));
-
- /* convert width/height to slots */
- w = DIV_ROUND_UP(w, geom[fmt].slot_w);
- h = DIV_ROUND_UP(h, geom[fmt].slot_h);
-
- /* convert alignment to slots */
- min_align = max(min_align, (geom[fmt].slot_w * geom[fmt].cpp));
- align = ALIGN(align, min_align);
- align /= geom[fmt].slot_w * geom[fmt].cpp;
-
- block->fmt = fmt;
-
- ret = tcm_reserve_2d(containers[fmt], w, h, align, &block->area);
- if (ret) {
- kfree(block);
- return ERR_PTR(-ENOMEM);
- }
-
- /* add to allocation list */
- spin_lock_irqsave(&list_lock, flags);
- list_add(&block->alloc_node, &omap_dmm->alloc_head);
- spin_unlock_irqrestore(&list_lock, flags);
-
- return block;
-}
-
-struct tiler_block *tiler_reserve_1d(size_t size)
-{
- struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
- int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- unsigned long flags;
-
- if (!block)
- return ERR_PTR(-ENOMEM);
-
- block->fmt = TILFMT_PAGE;
-
- if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
- &block->area)) {
- kfree(block);
- return ERR_PTR(-ENOMEM);
- }
-
- spin_lock_irqsave(&list_lock, flags);
- list_add(&block->alloc_node, &omap_dmm->alloc_head);
- spin_unlock_irqrestore(&list_lock, flags);
-
- return block;
-}
-
-/* note: if you have pin'd pages, you should have already unpin'd first! */
-int tiler_release(struct tiler_block *block)
-{
- int ret = tcm_free(&block->area);
- unsigned long flags;
-
- if (block->area.tcm)
- dev_err(omap_dmm->dev, "failed to release block\n");
-
- spin_lock_irqsave(&list_lock, flags);
- list_del(&block->alloc_node);
- spin_unlock_irqrestore(&list_lock, flags);
-
- kfree(block);
- return ret;
-}
-
-/*
- * Utils
- */
-
-/* calculate the tiler space address of a pixel in a view orientation...
- * below description copied from the display subsystem section of TRM:
- *
- * When the TILER is addressed, the bits:
- * [28:27] = 0x0 for 8-bit tiled
- * 0x1 for 16-bit tiled
- * 0x2 for 32-bit tiled
- * 0x3 for page mode
- * [31:29] = 0x0 for 0-degree view
- * 0x1 for 180-degree view + mirroring
- * 0x2 for 0-degree view + mirroring
- * 0x3 for 180-degree view
- * 0x4 for 270-degree view + mirroring
- * 0x5 for 270-degree view
- * 0x6 for 90-degree view
- * 0x7 for 90-degree view + mirroring
- * Otherwise the bits indicated the corresponding bit address to access
- * the SDRAM.
- */
-static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
-{
- u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
-
- x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
- y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
- alignment = geom[fmt].x_shft + geom[fmt].y_shft;
-
- /* validate coordinate */
- x_mask = MASK(x_bits);
- y_mask = MASK(y_bits);
-
- if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
- DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
- x, x, x_mask, y, y, y_mask);
- return 0;
- }
-
- /* account for mirroring */
- if (orient & MASK_X_INVERT)
- x ^= x_mask;
- if (orient & MASK_Y_INVERT)
- y ^= y_mask;
-
- /* get coordinate address */
- if (orient & MASK_XY_FLIP)
- tmp = ((x << y_bits) + y);
- else
- tmp = ((y << x_bits) + x);
-
- return TIL_ADDR((tmp << alignment), orient, fmt);
-}
-
-dma_addr_t tiler_ssptr(struct tiler_block *block)
-{
- BUG_ON(!validfmt(block->fmt));
-
- return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
- block->area.p0.x * geom[block->fmt].slot_w,
- block->area.p0.y * geom[block->fmt].slot_h);
-}
-
-dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
- uint32_t x, uint32_t y)
-{
- struct tcm_pt *p = &block->area.p0;
- BUG_ON(!validfmt(block->fmt));
-
- return tiler_get_address(block->fmt, orient,
- (p->x * geom[block->fmt].slot_w) + x,
- (p->y * geom[block->fmt].slot_h) + y);
-}
-
-void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
-{
- BUG_ON(!validfmt(fmt));
- *w = round_up(*w, geom[fmt].slot_w);
- *h = round_up(*h, geom[fmt].slot_h);
-}
-
-uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient)
-{
- BUG_ON(!validfmt(fmt));
-
- if (orient & MASK_XY_FLIP)
- return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
- else
- return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
-}
-
-size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h)
-{
- tiler_align(fmt, &w, &h);
- return geom[fmt].cpp * w * h;
-}
-
-size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
-{
- BUG_ON(!validfmt(fmt));
- return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
-}
-
-bool dmm_is_available(void)
-{
- return omap_dmm ? true : false;
-}
-
-static int omap_dmm_remove(struct platform_device *dev)
-{
- struct tiler_block *block, *_block;
- int i;
- unsigned long flags;
-
- if (omap_dmm) {
- /* free all area regions */
- spin_lock_irqsave(&list_lock, flags);
- list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
- alloc_node) {
- list_del(&block->alloc_node);
- kfree(block);
- }
- spin_unlock_irqrestore(&list_lock, flags);
-
- for (i = 0; i < omap_dmm->num_lut; i++)
- if (omap_dmm->tcm && omap_dmm->tcm[i])
- omap_dmm->tcm[i]->deinit(omap_dmm->tcm[i]);
- kfree(omap_dmm->tcm);
-
- kfree(omap_dmm->engines);
- if (omap_dmm->refill_va)
- dma_free_writecombine(omap_dmm->dev,
- REFILL_BUFFER_SIZE * omap_dmm->num_engines,
- omap_dmm->refill_va,
- omap_dmm->refill_pa);
- if (omap_dmm->dummy_page)
- __free_page(omap_dmm->dummy_page);
-
- if (omap_dmm->irq > 0)
- free_irq(omap_dmm->irq, omap_dmm);
-
- iounmap(omap_dmm->base);
- kfree(omap_dmm);
- omap_dmm = NULL;
- }
-
- return 0;
-}
-
-static int omap_dmm_probe(struct platform_device *dev)
-{
- int ret = -EFAULT, i;
- struct tcm_area area = {0};
- u32 hwinfo, pat_geom;
- struct resource *mem;
-
- omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
- if (!omap_dmm)
- goto fail;
-
- /* initialize lists */
- INIT_LIST_HEAD(&omap_dmm->alloc_head);
- INIT_LIST_HEAD(&omap_dmm->idle_head);
-
- init_waitqueue_head(&omap_dmm->engine_queue);
-
- /* lookup hwmod data - base address and irq */
- mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&dev->dev, "failed to get base address resource\n");
- goto fail;
- }
-
- omap_dmm->base = ioremap(mem->start, SZ_2K);
-
- if (!omap_dmm->base) {
- dev_err(&dev->dev, "failed to get dmm base address\n");
- goto fail;
- }
-
- omap_dmm->irq = platform_get_irq(dev, 0);
- if (omap_dmm->irq < 0) {
- dev_err(&dev->dev, "failed to get IRQ resource\n");
- goto fail;
- }
-
- omap_dmm->dev = &dev->dev;
-
- hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
- omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
- omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
- omap_dmm->container_width = 256;
- omap_dmm->container_height = 128;
-
- atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
-
- /* read out actual LUT width and height */
- pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
- omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
- omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
-
- /* increment LUT by one if on OMAP5 */
- /* LUT has twice the height, and is split into a separate container */
- if (omap_dmm->lut_height != omap_dmm->container_height)
- omap_dmm->num_lut++;
-
- /* initialize DMM registers */
- writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__0);
- writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__1);
- writel(0x80808080, omap_dmm->base + DMM_PAT_VIEW_MAP__0);
- writel(0x80000000, omap_dmm->base + DMM_PAT_VIEW_MAP_BASE);
- writel(0x88888888, omap_dmm->base + DMM_TILER_OR__0);
- writel(0x88888888, omap_dmm->base + DMM_TILER_OR__1);
-
- ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
- "omap_dmm_irq_handler", omap_dmm);
-
- if (ret) {
- dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
- omap_dmm->irq, ret);
- omap_dmm->irq = -1;
- goto fail;
- }
-
- /* Enable all interrupts for each refill engine except
- * ERR_LUT_MISS<n> (which is just advisory, and we don't care
- * about because we want to be able to refill live scanout
- * buffers for accelerated pan/scroll) and FILL_DSC<n> which
- * we just generally don't care about.
- */
- writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
-
- omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
- if (!omap_dmm->dummy_page) {
- dev_err(&dev->dev, "could not allocate dummy page\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- /* set dma mask for device */
- /* NOTE: this is a workaround for the hwmod not initializing properly */
- dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-
- omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
-
- /* alloc refill memory */
- omap_dmm->refill_va = dma_alloc_writecombine(&dev->dev,
- REFILL_BUFFER_SIZE * omap_dmm->num_engines,
- &omap_dmm->refill_pa, GFP_KERNEL);
- if (!omap_dmm->refill_va) {
- dev_err(&dev->dev, "could not allocate refill memory\n");
- goto fail;
- }
-
- /* alloc engines */
- omap_dmm->engines = kcalloc(omap_dmm->num_engines,
- sizeof(struct refill_engine), GFP_KERNEL);
- if (!omap_dmm->engines) {
- ret = -ENOMEM;
- goto fail;
- }
-
- for (i = 0; i < omap_dmm->num_engines; i++) {
- omap_dmm->engines[i].id = i;
- omap_dmm->engines[i].dmm = omap_dmm;
- omap_dmm->engines[i].refill_va = omap_dmm->refill_va +
- (REFILL_BUFFER_SIZE * i);
- omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa +
- (REFILL_BUFFER_SIZE * i);
- init_waitqueue_head(&omap_dmm->engines[i].wait_for_refill);
-
- list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
- }
-
- omap_dmm->tcm = kcalloc(omap_dmm->num_lut, sizeof(*omap_dmm->tcm),
- GFP_KERNEL);
- if (!omap_dmm->tcm) {
- ret = -ENOMEM;
- goto fail;
- }
-
- /* init containers */
- /* Each LUT is associated with a TCM (container manager). We use the
- lut_id to denote the lut_id used to identify the correct LUT for
- programming during reill operations */
- for (i = 0; i < omap_dmm->num_lut; i++) {
- omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
- omap_dmm->container_height,
- NULL);
-
- if (!omap_dmm->tcm[i]) {
- dev_err(&dev->dev, "failed to allocate container\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- omap_dmm->tcm[i]->lut_id = i;
- }
-
- /* assign access mode containers to applicable tcm container */
- /* OMAP 4 has 1 container for all 4 views */
- /* OMAP 5 has 2 containers, 1 for 2D and 1 for 1D */
- containers[TILFMT_8BIT] = omap_dmm->tcm[0];
- containers[TILFMT_16BIT] = omap_dmm->tcm[0];
- containers[TILFMT_32BIT] = omap_dmm->tcm[0];
-
- if (omap_dmm->container_height != omap_dmm->lut_height) {
- /* second LUT is used for PAGE mode. Programming must use
- y offset that is added to all y coordinates. LUT id is still
- 0, because it is the same LUT, just the upper 128 lines */
- containers[TILFMT_PAGE] = omap_dmm->tcm[1];
- omap_dmm->tcm[1]->y_offset = OMAP5_LUT_OFFSET;
- omap_dmm->tcm[1]->lut_id = 0;
- } else {
- containers[TILFMT_PAGE] = omap_dmm->tcm[0];
- }
-
- area = (struct tcm_area) {
- .tcm = NULL,
- .p1.x = omap_dmm->container_width - 1,
- .p1.y = omap_dmm->container_height - 1,
- };
-
- /* initialize all LUTs to dummy page entries */
- for (i = 0; i < omap_dmm->num_lut; i++) {
- area.tcm = omap_dmm->tcm[i];
- if (fill(&area, NULL, 0, 0, true))
- dev_err(omap_dmm->dev, "refill failed");
- }
-
- dev_info(omap_dmm->dev, "initialized all PAT entries\n");
-
- return 0;
-
-fail:
- if (omap_dmm_remove(dev))
- dev_err(&dev->dev, "cleanup failed\n");
- return ret;
-}
-
-/*
- * debugfs support
- */
-
-#ifdef CONFIG_DEBUG_FS
-
-static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-static const char *special = ".,:;'\"`~!^-+";
-
-static void fill_map(char **map, int xdiv, int ydiv, struct tcm_area *a,
- char c, bool ovw)
-{
- int x, y;
- for (y = a->p0.y / ydiv; y <= a->p1.y / ydiv; y++)
- for (x = a->p0.x / xdiv; x <= a->p1.x / xdiv; x++)
- if (map[y][x] == ' ' || ovw)
- map[y][x] = c;
-}
-
-static void fill_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p,
- char c)
-{
- map[p->y / ydiv][p->x / xdiv] = c;
-}
-
-static char read_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p)
-{
- return map[p->y / ydiv][p->x / xdiv];
-}
-
-static int map_width(int xdiv, int x0, int x1)
-{
- return (x1 / xdiv) - (x0 / xdiv) + 1;
-}
-
-static void text_map(char **map, int xdiv, char *nice, int yd, int x0, int x1)
-{
- char *p = map[yd] + (x0 / xdiv);
- int w = (map_width(xdiv, x0, x1) - strlen(nice)) / 2;
- if (w >= 0) {
- p += w;
- while (*nice)
- *p++ = *nice++;
- }
-}
-
-static void map_1d_info(char **map, int xdiv, int ydiv, char *nice,
- struct tcm_area *a)
-{
- sprintf(nice, "%dK", tcm_sizeof(*a) * 4);
- if (a->p0.y + 1 < a->p1.y) {
- text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv, 0,
- 256 - 1);
- } else if (a->p0.y < a->p1.y) {
- if (strlen(nice) < map_width(xdiv, a->p0.x, 256 - 1))
- text_map(map, xdiv, nice, a->p0.y / ydiv,
- a->p0.x + xdiv, 256 - 1);
- else if (strlen(nice) < map_width(xdiv, 0, a->p1.x))
- text_map(map, xdiv, nice, a->p1.y / ydiv,
- 0, a->p1.y - xdiv);
- } else if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x)) {
- text_map(map, xdiv, nice, a->p0.y / ydiv, a->p0.x, a->p1.x);
- }
-}
-
-static void map_2d_info(char **map, int xdiv, int ydiv, char *nice,
- struct tcm_area *a)
-{
- sprintf(nice, "(%d*%d)", tcm_awidth(*a), tcm_aheight(*a));
- if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x))
- text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv,
- a->p0.x, a->p1.x);
-}
-
-int tiler_map_show(struct seq_file *s, void *arg)
-{
- int xdiv = 2, ydiv = 1;
- char **map = NULL, *global_map;
- struct tiler_block *block;
- struct tcm_area a, p;
- int i;
- const char *m2d = alphabet;
- const char *a2d = special;
- const char *m2dp = m2d, *a2dp = a2d;
- char nice[128];
- int h_adj;
- int w_adj;
- unsigned long flags;
- int lut_idx;
-
-
- if (!omap_dmm) {
- /* early return if dmm/tiler device is not initialized */
- return 0;
- }
-
- h_adj = omap_dmm->container_height / ydiv;
- w_adj = omap_dmm->container_width / xdiv;
-
- map = kmalloc(h_adj * sizeof(*map), GFP_KERNEL);
- global_map = kmalloc((w_adj + 1) * h_adj, GFP_KERNEL);
-
- if (!map || !global_map)
- goto error;
-
- for (lut_idx = 0; lut_idx < omap_dmm->num_lut; lut_idx++) {
- memset(map, 0, sizeof(h_adj * sizeof(*map)));
- memset(global_map, ' ', (w_adj + 1) * h_adj);
-
- for (i = 0; i < omap_dmm->container_height; i++) {
- map[i] = global_map + i * (w_adj + 1);
- map[i][w_adj] = 0;
- }
-
- spin_lock_irqsave(&list_lock, flags);
-
- list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
- if (block->area.tcm == omap_dmm->tcm[lut_idx]) {
- if (block->fmt != TILFMT_PAGE) {
- fill_map(map, xdiv, ydiv, &block->area,
- *m2dp, true);
- if (!*++a2dp)
- a2dp = a2d;
- if (!*++m2dp)
- m2dp = m2d;
- map_2d_info(map, xdiv, ydiv, nice,
- &block->area);
- } else {
- bool start = read_map_pt(map, xdiv,
- ydiv, &block->area.p0) == ' ';
- bool end = read_map_pt(map, xdiv, ydiv,
- &block->area.p1) == ' ';
-
- tcm_for_each_slice(a, block->area, p)
- fill_map(map, xdiv, ydiv, &a,
- '=', true);
- fill_map_pt(map, xdiv, ydiv,
- &block->area.p0,
- start ? '<' : 'X');
- fill_map_pt(map, xdiv, ydiv,
- &block->area.p1,
- end ? '>' : 'X');
- map_1d_info(map, xdiv, ydiv, nice,
- &block->area);
- }
- }
- }
-
- spin_unlock_irqrestore(&list_lock, flags);
-
- if (s) {
- seq_printf(s, "CONTAINER %d DUMP BEGIN\n", lut_idx);
- for (i = 0; i < 128; i++)
- seq_printf(s, "%03d:%s\n", i, map[i]);
- seq_printf(s, "CONTAINER %d DUMP END\n", lut_idx);
- } else {
- dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP BEGIN\n",
- lut_idx);
- for (i = 0; i < 128; i++)
- dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
- dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP END\n",
- lut_idx);
- }
- }
-
-error:
- kfree(map);
- kfree(global_map);
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_PM
-static int omap_dmm_resume(struct device *dev)
-{
- struct tcm_area area;
- int i;
-
- if (!omap_dmm)
- return -ENODEV;
-
- area = (struct tcm_area) {
- .tcm = NULL,
- .p1.x = omap_dmm->container_width - 1,
- .p1.y = omap_dmm->container_height - 1,
- };
-
- /* initialize all LUTs to dummy page entries */
- for (i = 0; i < omap_dmm->num_lut; i++) {
- area.tcm = omap_dmm->tcm[i];
- if (fill(&area, NULL, 0, 0, true))
- dev_err(dev, "refill failed");
- }
-
- return 0;
-}
-
-static const struct dev_pm_ops omap_dmm_pm_ops = {
- .resume = omap_dmm_resume,
-};
-#endif
-
-struct platform_driver omap_dmm_driver = {
- .probe = omap_dmm_probe,
- .remove = omap_dmm_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = DMM_DRIVER_NAME,
-#ifdef CONFIG_PM
- .pm = &omap_dmm_pm_ops,
-#endif
- },
-};
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
-MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
-MODULE_ALIAS("platform:" DMM_DRIVER_NAME);
diff --git a/drivers/staging/omapdrm/omap_dmm_tiler.h b/drivers/staging/omapdrm/omap_dmm_tiler.h
deleted file mode 100644
index 4fdd61e54bd..00000000000
--- a/drivers/staging/omapdrm/omap_dmm_tiler.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- *
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Rob Clark <rob@ti.com>
- * Andy Gross <andy.gross@ti.com>
- *
- * 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 version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifndef OMAP_DMM_TILER_H
-#define OMAP_DMM_TILER_H
-
-#include "omap_drv.h"
-#include "tcm.h"
-
-enum tiler_fmt {
- TILFMT_8BIT = 0,
- TILFMT_16BIT,
- TILFMT_32BIT,
- TILFMT_PAGE,
- TILFMT_NFORMATS
-};
-
-struct pat_area {
- u32 x0:8;
- u32 y0:8;
- u32 x1:8;
- u32 y1:8;
-};
-
-struct tiler_block {
- struct list_head alloc_node; /* node for global block list */
- struct tcm_area area; /* area */
- enum tiler_fmt fmt; /* format */
-};
-
-/* bits representing the same slot in DMM-TILER hw-block */
-#define SLOT_WIDTH_BITS 6
-#define SLOT_HEIGHT_BITS 6
-
-/* bits reserved to describe coordinates in DMM-TILER hw-block */
-#define CONT_WIDTH_BITS 14
-#define CONT_HEIGHT_BITS 13
-
-/* calculated constants */
-#define TILER_PAGE (1 << (SLOT_WIDTH_BITS + SLOT_HEIGHT_BITS))
-#define TILER_WIDTH (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
-#define TILER_HEIGHT (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))
-
-/*
-Table 15-11. Coding and Description of TILER Orientations
-S Y X Description Alternate description
-0 0 0 0-degree view Natural view
-0 0 1 0-degree view with vertical mirror 180-degree view with horizontal mirror
-0 1 0 0-degree view with horizontal mirror 180-degree view with vertical mirror
-0 1 1 180-degree view
-1 0 0 90-degree view with vertical mirror 270-degree view with horizontal mirror
-1 0 1 270-degree view
-1 1 0 90-degree view
-1 1 1 90-degree view with horizontal mirror 270-degree view with vertical mirror
- */
-#define MASK_XY_FLIP (1 << 31)
-#define MASK_Y_INVERT (1 << 30)
-#define MASK_X_INVERT (1 << 29)
-#define SHIFT_ACC_MODE 27
-#define MASK_ACC_MODE 3
-
-#define MASK(bits) ((1 << (bits)) - 1)
-
-#define TILVIEW_8BIT 0x60000000u
-#define TILVIEW_16BIT (TILVIEW_8BIT + VIEW_SIZE)
-#define TILVIEW_32BIT (TILVIEW_16BIT + VIEW_SIZE)
-#define TILVIEW_PAGE (TILVIEW_32BIT + VIEW_SIZE)
-#define TILVIEW_END (TILVIEW_PAGE + VIEW_SIZE)
-
-/* create tsptr by adding view orientation and access mode */
-#define TIL_ADDR(x, orient, a)\
- ((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
-
-#ifdef CONFIG_DEBUG_FS
-int tiler_map_show(struct seq_file *s, void *arg);
-#endif
-
-/* pin/unpin */
-int tiler_pin(struct tiler_block *block, struct page **pages,
- uint32_t npages, uint32_t roll, bool wait);
-int tiler_unpin(struct tiler_block *block);
-
-/* reserve/release */
-struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w, uint16_t h,
- uint16_t align);
-struct tiler_block *tiler_reserve_1d(size_t size);
-int tiler_release(struct tiler_block *block);
-
-/* utilities */
-dma_addr_t tiler_ssptr(struct tiler_block *block);
-dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
- uint32_t x, uint32_t y);
-uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient);
-size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
-size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
-void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
-bool dmm_is_available(void);
-
-extern struct platform_driver omap_dmm_driver;
-
-/* GEM bo flags -> tiler fmt */
-static inline enum tiler_fmt gem2fmt(uint32_t flags)
-{
- switch (flags & OMAP_BO_TILED) {
- case OMAP_BO_TILED_8:
- return TILFMT_8BIT;
- case OMAP_BO_TILED_16:
- return TILFMT_16BIT;
- case OMAP_BO_TILED_32:
- return TILFMT_32BIT;
- default:
- return TILFMT_PAGE;
- }
-}
-
-static inline bool validfmt(enum tiler_fmt fmt)
-{
- switch (fmt) {
- case TILFMT_8BIT:
- case TILFMT_16BIT:
- case TILFMT_32BIT:
- case TILFMT_PAGE:
- return true;
- default:
- return false;
- }
-}
-
-#endif
diff --git a/drivers/staging/omapdrm/omap_drm.h b/drivers/staging/omapdrm/omap_drm.h
deleted file mode 100644
index f0ac34a8973..00000000000
--- a/drivers/staging/omapdrm/omap_drm.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * include/drm/omap_drm.h
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP_DRM_H__
-#define __OMAP_DRM_H__
-
-#include <drm/drm.h>
-
-/* Please note that modifications to all structs defined here are
- * subject to backwards-compatibility constraints.
- */
-
-#define OMAP_PARAM_CHIPSET_ID 1 /* ie. 0x3430, 0x4430, etc */
-
-struct drm_omap_param {
- uint64_t param; /* in */
- uint64_t value; /* in (set_param), out (get_param) */
-};
-
-#define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */
-#define OMAP_BO_CACHE_MASK 0x00000006 /* cache type mask, see cache modes */
-#define OMAP_BO_TILED_MASK 0x00000f00 /* tiled mapping mask, see tiled modes */
-
-/* cache modes */
-#define OMAP_BO_CACHED 0x00000000 /* default */
-#define OMAP_BO_WC 0x00000002 /* write-combine */
-#define OMAP_BO_UNCACHED 0x00000004 /* strongly-ordered (uncached) */
-
-/* tiled modes */
-#define OMAP_BO_TILED_8 0x00000100
-#define OMAP_BO_TILED_16 0x00000200
-#define OMAP_BO_TILED_32 0x00000300
-#define OMAP_BO_TILED (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
-
-union omap_gem_size {
- uint32_t bytes; /* (for non-tiled formats) */
- struct {
- uint16_t width;
- uint16_t height;
- } tiled; /* (for tiled formats) */
-};
-
-struct drm_omap_gem_new {
- union omap_gem_size size; /* in */
- uint32_t flags; /* in */
- uint32_t handle; /* out */
- uint32_t __pad;
-};
-
-/* mask of operations: */
-enum omap_gem_op {
- OMAP_GEM_READ = 0x01,
- OMAP_GEM_WRITE = 0x02,
-};
-
-struct drm_omap_gem_cpu_prep {
- uint32_t handle; /* buffer handle (in) */
- uint32_t op; /* mask of omap_gem_op (in) */
-};
-
-struct drm_omap_gem_cpu_fini {
- uint32_t handle; /* buffer handle (in) */
- uint32_t op; /* mask of omap_gem_op (in) */
- /* TODO maybe here we pass down info about what regions are touched
- * by sw so we can be clever about cache ops? For now a placeholder,
- * set to zero and we just do full buffer flush..
- */
- uint32_t nregions;
- uint32_t __pad;
-};
-
-struct drm_omap_gem_info {
- uint32_t handle; /* buffer handle (in) */
- uint32_t pad;
- uint64_t offset; /* mmap offset (out) */
- /* note: in case of tiled buffers, the user virtual size can be
- * different from the physical size (ie. how many pages are needed
- * to back the object) which is returned in DRM_IOCTL_GEM_OPEN..
- * This size here is the one that should be used if you want to
- * mmap() the buffer:
- */
- uint32_t size; /* virtual size for mmap'ing (out) */
- uint32_t __pad;
-};
-
-#define DRM_OMAP_GET_PARAM 0x00
-#define DRM_OMAP_SET_PARAM 0x01
-/* placeholder for plugin-api
-#define DRM_OMAP_GET_BASE 0x02
-*/
-#define DRM_OMAP_GEM_NEW 0x03
-#define DRM_OMAP_GEM_CPU_PREP 0x04
-#define DRM_OMAP_GEM_CPU_FINI 0x05
-#define DRM_OMAP_GEM_INFO 0x06
-#define DRM_OMAP_NUM_IOCTLS 0x07
-
-#define DRM_IOCTL_OMAP_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_PARAM, struct drm_omap_param)
-#define DRM_IOCTL_OMAP_SET_PARAM DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_SET_PARAM, struct drm_omap_param)
-/* placeholder for plugin-api
-#define DRM_IOCTL_OMAP_GET_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_BASE, struct drm_omap_get_base)
-*/
-#define DRM_IOCTL_OMAP_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_NEW, struct drm_omap_gem_new)
-#define DRM_IOCTL_OMAP_GEM_CPU_PREP DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_PREP, struct drm_omap_gem_cpu_prep)
-#define DRM_IOCTL_OMAP_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_FINI, struct drm_omap_gem_cpu_fini)
-#define DRM_IOCTL_OMAP_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_INFO, struct drm_omap_gem_info)
-
-#endif /* __OMAP_DRM_H__ */
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
deleted file mode 100644
index 480dc343446..00000000000
--- a/drivers/staging/omapdrm/omap_drv.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_drv.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include "drm_crtc_helper.h"
-#include "drm_fb_helper.h"
-#include "omap_dmm_tiler.h"
-
-#define DRIVER_NAME MODULE_NAME
-#define DRIVER_DESC "OMAP DRM"
-#define DRIVER_DATE "20110917"
-#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 0
-#define DRIVER_PATCHLEVEL 0
-
-static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS;
-
-MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs");
-module_param(num_crtc, int, 0600);
-
-/*
- * mode config funcs
- */
-
-/* Notes about mapping DSS and DRM entities:
- * CRTC: overlay
- * encoder: manager.. with some extension to allow one primary CRTC
- * and zero or more video CRTC's to be mapped to one encoder?
- * connector: dssdev.. manager can be attached/detached from different
- * devices
- */
-
-static void omap_fb_output_poll_changed(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- DBG("dev=%p", dev);
- if (priv->fbdev)
- drm_fb_helper_hotplug_event(priv->fbdev);
-}
-
-static const struct drm_mode_config_funcs omap_mode_config_funcs = {
- .fb_create = omap_framebuffer_create,
- .output_poll_changed = omap_fb_output_poll_changed,
-};
-
-static int get_connector_type(struct omap_dss_device *dssdev)
-{
- switch (dssdev->type) {
- case OMAP_DISPLAY_TYPE_HDMI:
- return DRM_MODE_CONNECTOR_HDMIA;
- case OMAP_DISPLAY_TYPE_DPI:
- if (!strcmp(dssdev->name, "dvi"))
- return DRM_MODE_CONNECTOR_DVID;
- /* fallthrough */
- default:
- return DRM_MODE_CONNECTOR_Unknown;
- }
-}
-
-static int omap_modeset_init(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_dss_device *dssdev = NULL;
- int num_ovls = dss_feat_get_num_ovls();
- int id;
-
- drm_mode_config_init(dev);
-
- omap_drm_irq_install(dev);
-
- /*
- * Create private planes and CRTCs for the last NUM_CRTCs overlay
- * plus manager:
- */
- for (id = 0; id < min(num_crtc, num_ovls); id++) {
- struct drm_plane *plane;
- struct drm_crtc *crtc;
-
- plane = omap_plane_init(dev, id, true);
- crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);
-
- BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
- priv->crtcs[id] = crtc;
- priv->num_crtcs++;
-
- priv->planes[id] = plane;
- priv->num_planes++;
- }
-
- /*
- * Create normal planes for the remaining overlays:
- */
- for (; id < num_ovls; id++) {
- struct drm_plane *plane = omap_plane_init(dev, id, false);
-
- BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
- priv->planes[priv->num_planes++] = plane;
- }
-
- for_each_dss_dev(dssdev) {
- struct drm_connector *connector;
- struct drm_encoder *encoder;
-
- if (!dssdev->driver) {
- dev_warn(dev->dev, "%s has no driver.. skipping it\n",
- dssdev->name);
- return 0;
- }
-
- if (!(dssdev->driver->get_timings ||
- dssdev->driver->read_edid)) {
- dev_warn(dev->dev, "%s driver does not support "
- "get_timings or read_edid.. skipping it!\n",
- dssdev->name);
- return 0;
- }
-
- encoder = omap_encoder_init(dev, dssdev);
-
- if (!encoder) {
- dev_err(dev->dev, "could not create encoder: %s\n",
- dssdev->name);
- return -ENOMEM;
- }
-
- connector = omap_connector_init(dev,
- get_connector_type(dssdev), dssdev, encoder);
-
- if (!connector) {
- dev_err(dev->dev, "could not create connector: %s\n",
- dssdev->name);
- return -ENOMEM;
- }
-
- BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
- BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
-
- priv->encoders[priv->num_encoders++] = encoder;
- priv->connectors[priv->num_connectors++] = connector;
-
- drm_mode_connector_attach_encoder(connector, encoder);
-
- /* figure out which crtc's we can connect the encoder to: */
- encoder->possible_crtcs = 0;
- for (id = 0; id < priv->num_crtcs; id++) {
- enum omap_dss_output_id supported_outputs =
- dss_feat_get_supported_outputs(pipe2chan(id));
- if (supported_outputs & dssdev->output->id)
- encoder->possible_crtcs |= (1 << id);
- }
- }
-
- dev->mode_config.min_width = 32;
- dev->mode_config.min_height = 32;
-
- /* note: eventually will need some cpu_is_omapXYZ() type stuff here
- * to fill in these limits properly on different OMAP generations..
- */
- dev->mode_config.max_width = 2048;
- dev->mode_config.max_height = 2048;
-
- dev->mode_config.funcs = &omap_mode_config_funcs;
-
- return 0;
-}
-
-static void omap_modeset_free(struct drm_device *dev)
-{
- drm_mode_config_cleanup(dev);
-}
-
-/*
- * drm ioctl funcs
- */
-
-
-static int ioctl_get_param(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_omap_param *args = data;
-
- DBG("%p: param=%llu", dev, args->param);
-
- switch (args->param) {
- case OMAP_PARAM_CHIPSET_ID:
- args->value = priv->omaprev;
- break;
- default:
- DBG("unknown parameter %lld", args->param);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int ioctl_set_param(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_omap_param *args = data;
-
- switch (args->param) {
- default:
- DBG("unknown parameter %lld", args->param);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int ioctl_gem_new(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_omap_gem_new *args = data;
- VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
- args->size.bytes, args->flags);
- return omap_gem_new_handle(dev, file_priv, args->size,
- args->flags, &args->handle);
-}
-
-static int ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_omap_gem_cpu_prep *args = data;
- struct drm_gem_object *obj;
- int ret;
-
- VERB("%p:%p: handle=%d, op=%x", dev, file_priv, args->handle, args->op);
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (!obj)
- return -ENOENT;
-
- ret = omap_gem_op_sync(obj, args->op);
-
- if (!ret)
- ret = omap_gem_op_start(obj, args->op);
-
- drm_gem_object_unreference_unlocked(obj);
-
- return ret;
-}
-
-static int ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_omap_gem_cpu_fini *args = data;
- struct drm_gem_object *obj;
- int ret;
-
- VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (!obj)
- return -ENOENT;
-
- /* XXX flushy, flushy */
- ret = 0;
-
- if (!ret)
- ret = omap_gem_op_finish(obj, args->op);
-
- drm_gem_object_unreference_unlocked(obj);
-
- return ret;
-}
-
-static int ioctl_gem_info(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_omap_gem_info *args = data;
- struct drm_gem_object *obj;
- int ret = 0;
-
- VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
- if (!obj)
- return -ENOENT;
-
- args->size = omap_gem_mmap_size(obj);
- args->offset = omap_gem_mmap_offset(obj);
-
- drm_gem_object_unreference_unlocked(obj);
-
- return ret;
-}
-
-struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = {
- DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_UNLOCKED|DRM_AUTH),
- DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_UNLOCKED|DRM_AUTH),
-};
-
-/*
- * drm driver funcs
- */
-
-/**
- * load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
- *
- * The driver load routine has to do several things:
- * - initialize the memory manager
- * - allocate initial config memory
- * - setup the DRM framebuffer with the allocated memory
- */
-static int dev_load(struct drm_device *dev, unsigned long flags)
-{
- struct omap_drm_platform_data *pdata = dev->dev->platform_data;
- struct omap_drm_private *priv;
- int ret;
-
- DBG("load: dev=%p", dev);
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->omaprev = pdata->omaprev;
-
- dev->dev_private = priv;
-
- priv->wq = alloc_ordered_workqueue("omapdrm", 0);
-
- INIT_LIST_HEAD(&priv->obj_list);
-
- omap_gem_init(dev);
-
- ret = omap_modeset_init(dev);
- if (ret) {
- dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
- dev->dev_private = NULL;
- kfree(priv);
- return ret;
- }
-
- ret = drm_vblank_init(dev, priv->num_crtcs);
- if (ret)
- dev_warn(dev->dev, "could not init vblank\n");
-
- priv->fbdev = omap_fbdev_init(dev);
- if (!priv->fbdev) {
- dev_warn(dev->dev, "omap_fbdev_init failed\n");
- /* well, limp along without an fbdev.. maybe X11 will work? */
- }
-
- /* store off drm_device for use in pm ops */
- dev_set_drvdata(dev->dev, dev);
-
- drm_kms_helper_poll_init(dev);
-
- return 0;
-}
-
-static int dev_unload(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
-
- DBG("unload: dev=%p", dev);
-
- drm_kms_helper_poll_fini(dev);
- drm_vblank_cleanup(dev);
- omap_drm_irq_uninstall(dev);
-
- omap_fbdev_free(dev);
- omap_modeset_free(dev);
- omap_gem_deinit(dev);
-
- flush_workqueue(priv->wq);
- destroy_workqueue(priv->wq);
-
- kfree(dev->dev_private);
- dev->dev_private = NULL;
-
- dev_set_drvdata(dev->dev, NULL);
-
- return 0;
-}
-
-static int dev_open(struct drm_device *dev, struct drm_file *file)
-{
- file->driver_priv = NULL;
-
- DBG("open: dev=%p, file=%p", dev, file);
-
- return 0;
-}
-
-static int dev_firstopen(struct drm_device *dev)
-{
- DBG("firstopen: dev=%p", dev);
- return 0;
-}
-
-/**
- * lastclose - clean up after all DRM clients have exited
- * @dev: DRM device
- *
- * Take care of cleaning up after all DRM clients have exited. In the
- * mode setting case, we want to restore the kernel's initial mode (just
- * in case the last client left us in a bad state).
- */
-static void dev_lastclose(struct drm_device *dev)
-{
- int i;
-
- /* we don't support vga-switcheroo.. so just make sure the fbdev
- * mode is active
- */
- struct omap_drm_private *priv = dev->dev_private;
- int ret;
-
- DBG("lastclose: dev=%p", dev);
-
- if (priv->rotation_prop) {
- /* need to restore default rotation state.. not sure
- * if there is a cleaner way to restore properties to
- * default state? Maybe a flag that properties should
- * automatically be restored to default state on
- * lastclose?
- */
- for (i = 0; i < priv->num_crtcs; i++) {
- drm_object_property_set_value(&priv->crtcs[i]->base,
- priv->rotation_prop, 0);
- }
-
- for (i = 0; i < priv->num_planes; i++) {
- drm_object_property_set_value(&priv->planes[i]->base,
- priv->rotation_prop, 0);
- }
- }
-
- mutex_lock(&dev->mode_config.mutex);
- ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
- mutex_unlock(&dev->mode_config.mutex);
- if (ret)
- DBG("failed to restore crtc mode");
-}
-
-static void dev_preclose(struct drm_device *dev, struct drm_file *file)
-{
- DBG("preclose: dev=%p", dev);
-}
-
-static void dev_postclose(struct drm_device *dev, struct drm_file *file)
-{
- DBG("postclose: dev=%p, file=%p", dev, file);
-}
-
-static const struct vm_operations_struct omap_gem_vm_ops = {
- .fault = omap_gem_fault,
- .open = drm_gem_vm_open,
- .close = drm_gem_vm_close,
-};
-
-static const struct file_operations omapdriver_fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .unlocked_ioctl = drm_ioctl,
- .release = drm_release,
- .mmap = omap_gem_mmap,
- .poll = drm_poll,
- .fasync = drm_fasync,
- .read = drm_read,
- .llseek = noop_llseek,
-};
-
-static struct drm_driver omap_drm_driver = {
- .driver_features =
- DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
- .load = dev_load,
- .unload = dev_unload,
- .open = dev_open,
- .firstopen = dev_firstopen,
- .lastclose = dev_lastclose,
- .preclose = dev_preclose,
- .postclose = dev_postclose,
- .get_vblank_counter = drm_vblank_count,
- .enable_vblank = omap_irq_enable_vblank,
- .disable_vblank = omap_irq_disable_vblank,
- .irq_preinstall = omap_irq_preinstall,
- .irq_postinstall = omap_irq_postinstall,
- .irq_uninstall = omap_irq_uninstall,
- .irq_handler = omap_irq_handler,
-#ifdef CONFIG_DEBUG_FS
- .debugfs_init = omap_debugfs_init,
- .debugfs_cleanup = omap_debugfs_cleanup,
-#endif
- .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
- .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
- .gem_prime_export = omap_gem_prime_export,
- .gem_prime_import = omap_gem_prime_import,
- .gem_init_object = omap_gem_init_object,
- .gem_free_object = omap_gem_free_object,
- .gem_vm_ops = &omap_gem_vm_ops,
- .dumb_create = omap_gem_dumb_create,
- .dumb_map_offset = omap_gem_dumb_map_offset,
- .dumb_destroy = omap_gem_dumb_destroy,
- .ioctls = ioctls,
- .num_ioctls = DRM_OMAP_NUM_IOCTLS,
- .fops = &omapdriver_fops,
- .name = DRIVER_NAME,
- .desc = DRIVER_DESC,
- .date = DRIVER_DATE,
- .major = DRIVER_MAJOR,
- .minor = DRIVER_MINOR,
- .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int pdev_suspend(struct platform_device *pDevice, pm_message_t state)
-{
- DBG("");
- return 0;
-}
-
-static int pdev_resume(struct platform_device *device)
-{
- DBG("");
- return 0;
-}
-
-static void pdev_shutdown(struct platform_device *device)
-{
- DBG("");
-}
-
-static int pdev_probe(struct platform_device *device)
-{
- DBG("%s", device->name);
- return drm_platform_init(&omap_drm_driver, device);
-}
-
-static int pdev_remove(struct platform_device *device)
-{
- DBG("");
- drm_platform_exit(&omap_drm_driver, device);
-
- platform_driver_unregister(&omap_dmm_driver);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static const struct dev_pm_ops omapdrm_pm_ops = {
- .resume = omap_gem_resume,
-};
-#endif
-
-struct platform_driver pdev = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &omapdrm_pm_ops,
-#endif
- },
- .probe = pdev_probe,
- .remove = pdev_remove,
- .suspend = pdev_suspend,
- .resume = pdev_resume,
- .shutdown = pdev_shutdown,
-};
-
-static int __init omap_drm_init(void)
-{
- DBG("init");
- if (platform_driver_register(&omap_dmm_driver)) {
- /* we can continue on without DMM.. so not fatal */
- dev_err(NULL, "DMM registration failed\n");
- }
- return platform_driver_register(&pdev);
-}
-
-static void __exit omap_drm_fini(void)
-{
- DBG("fini");
- platform_driver_unregister(&pdev);
-}
-
-/* need late_initcall() so we load after dss_driver's are loaded */
-late_initcall(omap_drm_init);
-module_exit(omap_drm_fini);
-
-MODULE_AUTHOR("Rob Clark <rob@ti.com>");
-MODULE_DESCRIPTION("OMAP DRM Display Driver");
-MODULE_ALIAS("platform:" DRIVER_NAME);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
deleted file mode 100644
index f921027e750..00000000000
--- a/drivers/staging/omapdrm/omap_drv.h
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_drv.h
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP_DRV_H__
-#define __OMAP_DRV_H__
-
-#include <video/omapdss.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <drm/drmP.h>
-#include <drm/drm_crtc_helper.h>
-#include <linux/platform_data/omap_drm.h>
-#include "omap_drm.h"
-
-
-#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
-
-#define MODULE_NAME "omapdrm"
-
-/* max # of mapper-id's that can be assigned.. todo, come up with a better
- * (but still inexpensive) way to store/access per-buffer mapper private
- * data..
- */
-#define MAX_MAPPERS 2
-
-/* parameters which describe (unrotated) coordinates of scanout within a fb: */
-struct omap_drm_window {
- uint32_t rotation;
- int32_t crtc_x, crtc_y; /* signed because can be offscreen */
- uint32_t crtc_w, crtc_h;
- uint32_t src_x, src_y;
- uint32_t src_w, src_h;
-};
-
-/* Once GO bit is set, we can't make further updates to shadowed registers
- * until the GO bit is cleared. So various parts in the kms code that need
- * to update shadowed registers queue up a pair of callbacks, pre_apply
- * which is called before setting GO bit, and post_apply that is called
- * after GO bit is cleared. The crtc manages the queuing, and everyone
- * else goes thru omap_crtc_apply() using these callbacks so that the
- * code which has to deal w/ GO bit state is centralized.
- */
-struct omap_drm_apply {
- struct list_head pending_node, queued_node;
- bool queued;
- void (*pre_apply)(struct omap_drm_apply *apply);
- void (*post_apply)(struct omap_drm_apply *apply);
-};
-
-/* For transiently registering for different DSS irqs that various parts
- * of the KMS code need during setup/configuration. We these are not
- * necessarily the same as what drm_vblank_get/put() are requesting, and
- * the hysteresis in drm_vblank_put() is not necessarily desirable for
- * internal housekeeping related irq usage.
- */
-struct omap_drm_irq {
- struct list_head node;
- uint32_t irqmask;
- bool registered;
- void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
-};
-
-/* For KMS code that needs to wait for a certain # of IRQs:
- */
-struct omap_irq_wait;
-struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
- uint32_t irqmask, int count);
-int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
- unsigned long timeout);
-
-struct omap_drm_private {
- uint32_t omaprev;
-
- unsigned int num_crtcs;
- struct drm_crtc *crtcs[8];
-
- unsigned int num_planes;
- struct drm_plane *planes[8];
-
- unsigned int num_encoders;
- struct drm_encoder *encoders[8];
-
- unsigned int num_connectors;
- struct drm_connector *connectors[8];
-
- struct drm_fb_helper *fbdev;
-
- struct workqueue_struct *wq;
-
- /* list of GEM objects: */
- struct list_head obj_list;
-
- bool has_dmm;
-
- /* properties: */
- struct drm_property *rotation_prop;
- struct drm_property *zorder_prop;
-
- /* irq handling: */
- struct list_head irq_list; /* list of omap_drm_irq */
- uint32_t vblank_mask; /* irq bits set for userspace vblank */
- struct omap_drm_irq error_handler;
-};
-
-/* this should probably be in drm-core to standardize amongst drivers */
-#define DRM_ROTATE_0 0
-#define DRM_ROTATE_90 1
-#define DRM_ROTATE_180 2
-#define DRM_ROTATE_270 3
-#define DRM_REFLECT_X 4
-#define DRM_REFLECT_Y 5
-
-#ifdef CONFIG_DEBUG_FS
-int omap_debugfs_init(struct drm_minor *minor);
-void omap_debugfs_cleanup(struct drm_minor *minor);
-void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
-void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m);
-void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
-#endif
-
-#ifdef CONFIG_PM
-int omap_gem_resume(struct device *dev);
-#endif
-
-int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
-void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
-void omap_irq_preinstall(struct drm_device *dev);
-int omap_irq_postinstall(struct drm_device *dev);
-void omap_irq_uninstall(struct drm_device *dev);
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
-int omap_drm_irq_uninstall(struct drm_device *dev);
-int omap_drm_irq_install(struct drm_device *dev);
-
-struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
-void omap_fbdev_free(struct drm_device *dev);
-
-const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
-enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
-int omap_crtc_apply(struct drm_crtc *crtc,
- struct omap_drm_apply *apply);
-struct drm_crtc *omap_crtc_init(struct drm_device *dev,
- struct drm_plane *plane, enum omap_channel channel, int id);
-
-struct drm_plane *omap_plane_init(struct drm_device *dev,
- int plane_id, bool private_plane);
-int omap_plane_dpms(struct drm_plane *plane, int mode);
-int omap_plane_mode_set(struct drm_plane *plane,
- struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h,
- void (*fxn)(void *), void *arg);
-void omap_plane_install_properties(struct drm_plane *plane,
- struct drm_mode_object *obj);
-int omap_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val);
-
-struct drm_encoder *omap_encoder_init(struct drm_device *dev,
- struct omap_dss_device *dssdev);
-int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled);
-int omap_encoder_update(struct drm_encoder *encoder,
- struct omap_overlay_manager *mgr,
- struct omap_video_timings *timings);
-
-struct drm_connector *omap_connector_init(struct drm_device *dev,
- int connector_type, struct omap_dss_device *dssdev,
- struct drm_encoder *encoder);
-struct drm_encoder *omap_connector_attached_encoder(
- struct drm_connector *connector);
-void omap_connector_flush(struct drm_connector *connector,
- int x, int y, int w, int h);
-
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
- struct omap_video_timings *timings);
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
- struct drm_display_mode *mode);
-
-uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
- uint32_t max_formats, enum omap_color_mode supported_modes);
-struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd);
-struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos);
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p);
-int omap_framebuffer_replace(struct drm_framebuffer *a,
- struct drm_framebuffer *b, void *arg,
- void (*unpin)(void *arg, struct drm_gem_object *bo));
-void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
- struct omap_drm_window *win, struct omap_overlay_info *info);
-struct drm_connector *omap_framebuffer_get_next_connector(
- struct drm_framebuffer *fb, struct drm_connector *from);
-void omap_framebuffer_flush(struct drm_framebuffer *fb,
- int x, int y, int w, int h);
-
-void omap_gem_init(struct drm_device *dev);
-void omap_gem_deinit(struct drm_device *dev);
-
-struct drm_gem_object *omap_gem_new(struct drm_device *dev,
- union omap_gem_size gsize, uint32_t flags);
-int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
- union omap_gem_size gsize, uint32_t flags, uint32_t *handle);
-void omap_gem_free_object(struct drm_gem_object *obj);
-int omap_gem_init_object(struct drm_gem_object *obj);
-void *omap_gem_vaddr(struct drm_gem_object *obj);
-int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset);
-int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle);
-int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args);
-int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma);
-int omap_gem_mmap_obj(struct drm_gem_object *obj,
- struct vm_area_struct *vma);
-int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op);
-int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op);
-int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op);
-int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
- void (*fxn)(void *arg), void *arg);
-int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll);
-void omap_gem_cpu_sync(struct drm_gem_object *obj, int pgoff);
-void omap_gem_dma_sync(struct drm_gem_object *obj,
- enum dma_data_direction dir);
-int omap_gem_get_paddr(struct drm_gem_object *obj,
- dma_addr_t *paddr, bool remap);
-int omap_gem_put_paddr(struct drm_gem_object *obj);
-int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
- bool remap);
-int omap_gem_put_pages(struct drm_gem_object *obj);
-uint32_t omap_gem_flags(struct drm_gem_object *obj);
-int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient,
- int x, int y, dma_addr_t *paddr);
-uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj);
-size_t omap_gem_mmap_size(struct drm_gem_object *obj);
-int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h);
-int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient);
-
-struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
- struct drm_gem_object *obj, int flags);
-struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
- struct dma_buf *buffer);
-
-static inline int align_pitch(int pitch, int width, int bpp)
-{
- int bytespp = (bpp + 7) / 8;
- /* in case someone tries to feed us a completely bogus stride: */
- pitch = max(pitch, width * bytespp);
- /* PVR needs alignment to 8 pixels.. right now that is the most
- * restrictive stride requirement..
- */
- return ALIGN(pitch, 8 * bytespp);
-}
-
-static inline enum omap_channel pipe2chan(int pipe)
-{
- int num_mgrs = dss_feat_get_num_mgrs();
-
- /*
- * We usually don't want to create a CRTC for each manager,
- * at least not until we have a way to expose private planes
- * to userspace. Otherwise there would not be enough video
- * pipes left for drm planes. The higher #'d managers tend
- * to have more features so start in reverse order.
- */
- return num_mgrs - pipe - 1;
-}
-
-/* map crtc to vblank mask */
-static inline uint32_t pipe2vbl(int crtc)
-{
- enum omap_channel channel = pipe2chan(crtc);
- return dispc_mgr_get_vsync_irq(channel);
-}
-
-static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)
-{
- struct omap_drm_private *priv = dev->dev_private;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)
- if (priv->crtcs[i] == crtc)
- return i;
-
- BUG(); /* bogus CRTC ptr */
- return -1;
-}
-
-/* should these be made into common util helpers?
- */
-
-static inline int objects_lookup(struct drm_device *dev,
- struct drm_file *filp, uint32_t pixel_format,
- struct drm_gem_object **bos, uint32_t *handles)
-{
- int i, n = drm_format_num_planes(pixel_format);
-
- for (i = 0; i < n; i++) {
- bos[i] = drm_gem_object_lookup(dev, filp, handles[i]);
- if (!bos[i])
- goto fail;
-
- }
-
- return 0;
-
-fail:
- while (--i > 0)
- drm_gem_object_unreference_unlocked(bos[i]);
-
- return -ENOENT;
-}
-
-#endif /* __OMAP_DRV_H__ */
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c
deleted file mode 100644
index 25fc0c7b4f6..00000000000
--- a/drivers/staging/omapdrm/omap_encoder.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_encoder.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-#include <linux/list.h>
-
-
-/*
- * encoder funcs
- */
-
-#define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
-
-/* The encoder and connector both map to same dssdev.. the encoder
- * handles the 'active' parts, ie. anything the modifies the state
- * of the hw, and the connector handles the 'read-only' parts, like
- * detecting connection and reading edid.
- */
-struct omap_encoder {
- struct drm_encoder base;
- struct omap_dss_device *dssdev;
-};
-
-static void omap_encoder_destroy(struct drm_encoder *encoder)
-{
- struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- drm_encoder_cleanup(encoder);
- kfree(omap_encoder);
-}
-
-static const struct drm_encoder_funcs omap_encoder_funcs = {
- .destroy = omap_encoder_destroy,
-};
-
-/*
- * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right
- * order.. the easiest way to work around this for now is to make all
- * the encoder-helper's no-op's and have the omap_crtc code take care
- * of the sequencing and call us in the right points.
- *
- * Eventually to handle connecting CRTCs to different encoders properly,
- * either the CRTC helpers need to change or we need to replace
- * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for
- * that.
- */
-
-static void omap_encoder_dpms(struct drm_encoder *encoder, int mode)
-{
-}
-
-static bool omap_encoder_mode_fixup(struct drm_encoder *encoder,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
-static void omap_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
-}
-
-static void omap_encoder_prepare(struct drm_encoder *encoder)
-{
-}
-
-static void omap_encoder_commit(struct drm_encoder *encoder)
-{
-}
-
-static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
- .dpms = omap_encoder_dpms,
- .mode_fixup = omap_encoder_mode_fixup,
- .mode_set = omap_encoder_mode_set,
- .prepare = omap_encoder_prepare,
- .commit = omap_encoder_commit,
-};
-
-/*
- * Instead of relying on the helpers for modeset, the omap_crtc code
- * calls these functions in the proper sequence.
- */
-
-int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled)
-{
- struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- struct omap_dss_device *dssdev = omap_encoder->dssdev;
- struct omap_dss_driver *dssdrv = dssdev->driver;
-
- if (enabled) {
- return dssdrv->enable(dssdev);
- } else {
- dssdrv->disable(dssdev);
- return 0;
- }
-}
-
-int omap_encoder_update(struct drm_encoder *encoder,
- struct omap_overlay_manager *mgr,
- struct omap_video_timings *timings)
-{
- struct drm_device *dev = encoder->dev;
- struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
- struct omap_dss_device *dssdev = omap_encoder->dssdev;
- struct omap_dss_driver *dssdrv = dssdev->driver;
- int ret;
-
- dssdev->output->manager = mgr;
-
- ret = dssdrv->check_timings(dssdev, timings);
- if (ret) {
- dev_err(dev->dev, "could not set timings: %d\n", ret);
- return ret;
- }
-
- dssdrv->set_timings(dssdev, timings);
-
- return 0;
-}
-
-/* initialize encoder */
-struct drm_encoder *omap_encoder_init(struct drm_device *dev,
- struct omap_dss_device *dssdev)
-{
- struct drm_encoder *encoder = NULL;
- struct omap_encoder *omap_encoder;
-
- omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
- if (!omap_encoder)
- goto fail;
-
- omap_encoder->dssdev = dssdev;
-
- encoder = &omap_encoder->base;
-
- drm_encoder_init(dev, encoder, &omap_encoder_funcs,
- DRM_MODE_ENCODER_TMDS);
- drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
-
- return encoder;
-
-fail:
- if (encoder)
- omap_encoder_destroy(encoder);
-
- return NULL;
-}
diff --git a/drivers/staging/omapdrm/omap_fb.c b/drivers/staging/omapdrm/omap_fb.c
deleted file mode 100644
index bb496994214..00000000000
--- a/drivers/staging/omapdrm/omap_fb.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_fb.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-#include "omap_dmm_tiler.h"
-
-#include "drm_crtc.h"
-#include "drm_crtc_helper.h"
-
-/*
- * framebuffer funcs
- */
-
-/* per-format info: */
-struct format {
- enum omap_color_mode dss_format;
- uint32_t pixel_format;
- struct {
- int stride_bpp; /* this times width is stride */
- int sub_y; /* sub-sample in y dimension */
- } planes[4];
- bool yuv;
-};
-
-static const struct format formats[] = {
- /* 16bpp [A]RGB: */
- { OMAP_DSS_COLOR_RGB16, DRM_FORMAT_RGB565, {{2, 1}}, false }, /* RGB16-565 */
- { OMAP_DSS_COLOR_RGB12U, DRM_FORMAT_RGBX4444, {{2, 1}}, false }, /* RGB12x-4444 */
- { OMAP_DSS_COLOR_RGBX16, DRM_FORMAT_XRGB4444, {{2, 1}}, false }, /* xRGB12-4444 */
- { OMAP_DSS_COLOR_RGBA16, DRM_FORMAT_RGBA4444, {{2, 1}}, false }, /* RGBA12-4444 */
- { OMAP_DSS_COLOR_ARGB16, DRM_FORMAT_ARGB4444, {{2, 1}}, false }, /* ARGB16-4444 */
- { OMAP_DSS_COLOR_XRGB16_1555, DRM_FORMAT_XRGB1555, {{2, 1}}, false }, /* xRGB15-1555 */
- { OMAP_DSS_COLOR_ARGB16_1555, DRM_FORMAT_ARGB1555, {{2, 1}}, false }, /* ARGB16-1555 */
- /* 24bpp RGB: */
- { OMAP_DSS_COLOR_RGB24P, DRM_FORMAT_RGB888, {{3, 1}}, false }, /* RGB24-888 */
- /* 32bpp [A]RGB: */
- { OMAP_DSS_COLOR_RGBX32, DRM_FORMAT_RGBX8888, {{4, 1}}, false }, /* RGBx24-8888 */
- { OMAP_DSS_COLOR_RGB24U, DRM_FORMAT_XRGB8888, {{4, 1}}, false }, /* xRGB24-8888 */
- { OMAP_DSS_COLOR_RGBA32, DRM_FORMAT_RGBA8888, {{4, 1}}, false }, /* RGBA32-8888 */
- { OMAP_DSS_COLOR_ARGB32, DRM_FORMAT_ARGB8888, {{4, 1}}, false }, /* ARGB32-8888 */
- /* YUV: */
- { OMAP_DSS_COLOR_NV12, DRM_FORMAT_NV12, {{1, 1}, {1, 2}}, true },
- { OMAP_DSS_COLOR_YUV2, DRM_FORMAT_YUYV, {{2, 1}}, true },
- { OMAP_DSS_COLOR_UYVY, DRM_FORMAT_UYVY, {{2, 1}}, true },
-};
-
-/* convert from overlay's pixel formats bitmask to an array of fourcc's */
-uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
- uint32_t max_formats, enum omap_color_mode supported_modes)
-{
- uint32_t nformats = 0;
- int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(formats) && nformats < max_formats; i++)
- if (formats[i].dss_format & supported_modes)
- pixel_formats[nformats++] = formats[i].pixel_format;
-
- return nformats;
-}
-
-/* per-plane info for the fb: */
-struct plane {
- struct drm_gem_object *bo;
- uint32_t pitch;
- uint32_t offset;
- dma_addr_t paddr;
-};
-
-#define to_omap_framebuffer(x) container_of(x, struct omap_framebuffer, base)
-
-struct omap_framebuffer {
- struct drm_framebuffer base;
- const struct format *format;
- struct plane planes[4];
-};
-
-static int omap_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- return drm_gem_handle_create(file_priv,
- omap_fb->planes[0].bo, handle);
-}
-
-static void omap_framebuffer_destroy(struct drm_framebuffer *fb)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- int i, n = drm_format_num_planes(fb->pixel_format);
-
- DBG("destroy: FB ID: %d (%p)", fb->base.id, fb);
-
- drm_framebuffer_cleanup(fb);
-
- for (i = 0; i < n; i++) {
- struct plane *plane = &omap_fb->planes[i];
- if (plane->bo)
- drm_gem_object_unreference_unlocked(plane->bo);
- }
-
- kfree(omap_fb);
-}
-
-static int omap_framebuffer_dirty(struct drm_framebuffer *fb,
- struct drm_file *file_priv, unsigned flags, unsigned color,
- struct drm_clip_rect *clips, unsigned num_clips)
-{
- int i;
-
- for (i = 0; i < num_clips; i++) {
- omap_framebuffer_flush(fb, clips[i].x1, clips[i].y1,
- clips[i].x2 - clips[i].x1,
- clips[i].y2 - clips[i].y1);
- }
-
- return 0;
-}
-
-static const struct drm_framebuffer_funcs omap_framebuffer_funcs = {
- .create_handle = omap_framebuffer_create_handle,
- .destroy = omap_framebuffer_destroy,
- .dirty = omap_framebuffer_dirty,
-};
-
-static uint32_t get_linear_addr(struct plane *plane,
- const struct format *format, int n, int x, int y)
-{
- uint32_t offset;
-
- offset = plane->offset +
- (x * format->planes[n].stride_bpp) +
- (y * plane->pitch / format->planes[n].sub_y);
-
- return plane->paddr + offset;
-}
-
-/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
- */
-void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
- struct omap_drm_window *win, struct omap_overlay_info *info)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- const struct format *format = omap_fb->format;
- struct plane *plane = &omap_fb->planes[0];
- uint32_t x, y, orient = 0;
-
- info->color_mode = format->dss_format;
-
- info->pos_x = win->crtc_x;
- info->pos_y = win->crtc_y;
- info->out_width = win->crtc_w;
- info->out_height = win->crtc_h;
- info->width = win->src_w;
- info->height = win->src_h;
-
- x = win->src_x;
- y = win->src_y;
-
- if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) {
- uint32_t w = win->src_w;
- uint32_t h = win->src_h;
-
- switch (win->rotation & 0xf) {
- default:
- dev_err(fb->dev->dev, "invalid rotation: %02x",
- (uint32_t)win->rotation);
- /* fallthru to default to no rotation */
- case 0:
- case BIT(DRM_ROTATE_0):
- orient = 0;
- break;
- case BIT(DRM_ROTATE_90):
- orient = MASK_XY_FLIP | MASK_X_INVERT;
- break;
- case BIT(DRM_ROTATE_180):
- orient = MASK_X_INVERT | MASK_Y_INVERT;
- break;
- case BIT(DRM_ROTATE_270):
- orient = MASK_XY_FLIP | MASK_Y_INVERT;
- break;
- }
-
- if (win->rotation & BIT(DRM_REFLECT_X))
- orient ^= MASK_X_INVERT;
-
- if (win->rotation & BIT(DRM_REFLECT_Y))
- orient ^= MASK_Y_INVERT;
-
- /* adjust x,y offset for flip/invert: */
- if (orient & MASK_XY_FLIP)
- swap(w, h);
- if (orient & MASK_Y_INVERT)
- y += h - 1;
- if (orient & MASK_X_INVERT)
- x += w - 1;
-
- omap_gem_rotated_paddr(plane->bo, orient, x, y, &info->paddr);
- info->rotation_type = OMAP_DSS_ROT_TILER;
- info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
- } else {
- info->paddr = get_linear_addr(plane, format, 0, x, y);
- info->rotation_type = OMAP_DSS_ROT_DMA;
- info->screen_width = plane->pitch;
- }
-
- /* convert to pixels: */
- info->screen_width /= format->planes[0].stride_bpp;
-
- if (format->dss_format == OMAP_DSS_COLOR_NV12) {
- plane = &omap_fb->planes[1];
-
- if (info->rotation_type == OMAP_DSS_ROT_TILER) {
- WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED));
- omap_gem_rotated_paddr(plane->bo, orient,
- x/2, y/2, &info->p_uv_addr);
- } else {
- info->p_uv_addr = get_linear_addr(plane, format, 1, x, y);
- }
- } else {
- info->p_uv_addr = 0;
- }
-}
-
-/* Call for unpin 'a' (if not NULL), and pin 'b' (if not NULL). Although
- * buffers to unpin are just pushed to the unpin fifo so that the
- * caller can defer unpin until vblank.
- *
- * Note if this fails (ie. something went very wrong!), all buffers are
- * unpinned, and the caller disables the overlay. We could have tried
- * to revert back to the previous set of pinned buffers but if things are
- * hosed there is no guarantee that would succeed.
- */
-int omap_framebuffer_replace(struct drm_framebuffer *a,
- struct drm_framebuffer *b, void *arg,
- void (*unpin)(void *arg, struct drm_gem_object *bo))
-{
- int ret = 0, i, na, nb;
- struct omap_framebuffer *ofba = to_omap_framebuffer(a);
- struct omap_framebuffer *ofbb = to_omap_framebuffer(b);
- uint32_t pinned_mask = 0;
-
- na = a ? drm_format_num_planes(a->pixel_format) : 0;
- nb = b ? drm_format_num_planes(b->pixel_format) : 0;
-
- for (i = 0; i < max(na, nb); i++) {
- struct plane *pa, *pb;
-
- pa = (i < na) ? &ofba->planes[i] : NULL;
- pb = (i < nb) ? &ofbb->planes[i] : NULL;
-
- if (pa)
- unpin(arg, pa->bo);
-
- if (pb && !ret) {
- ret = omap_gem_get_paddr(pb->bo, &pb->paddr, true);
- if (!ret) {
- omap_gem_dma_sync(pb->bo, DMA_TO_DEVICE);
- pinned_mask |= (1 << i);
- }
- }
- }
-
- if (ret) {
- /* something went wrong.. unpin what has been pinned */
- for (i = 0; i < nb; i++) {
- if (pinned_mask & (1 << i)) {
- struct plane *pb = &ofba->planes[i];
- unpin(arg, pb->bo);
- }
- }
- }
-
- return ret;
-}
-
-struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- if (p >= drm_format_num_planes(fb->pixel_format))
- return NULL;
- return omap_fb->planes[p].bo;
-}
-
-/* iterate thru all the connectors, returning ones that are attached
- * to the same fb..
- */
-struct drm_connector *omap_framebuffer_get_next_connector(
- struct drm_framebuffer *fb, struct drm_connector *from)
-{
- struct drm_device *dev = fb->dev;
- struct list_head *connector_list = &dev->mode_config.connector_list;
- struct drm_connector *connector = from;
-
- if (!from)
- return list_first_entry(connector_list, typeof(*from), head);
-
- list_for_each_entry_from(connector, connector_list, head) {
- if (connector != from) {
- struct drm_encoder *encoder = connector->encoder;
- struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
- if (crtc && crtc->fb == fb)
- return connector;
-
- }
- }
-
- return NULL;
-}
-
-/* flush an area of the framebuffer (in case of manual update display that
- * is not automatically flushed)
- */
-void omap_framebuffer_flush(struct drm_framebuffer *fb,
- int x, int y, int w, int h)
-{
- struct drm_connector *connector = NULL;
-
- VERB("flush: %d,%d %dx%d, fb=%p", x, y, w, h, fb);
-
- while ((connector = omap_framebuffer_get_next_connector(fb, connector))) {
- /* only consider connectors that are part of a chain */
- if (connector->encoder && connector->encoder->crtc) {
- /* TODO: maybe this should propagate thru the crtc who
- * could do the coordinate translation..
- */
- struct drm_crtc *crtc = connector->encoder->crtc;
- int cx = max(0, x - crtc->x);
- int cy = max(0, y - crtc->y);
- int cw = w + (x - crtc->x) - cx;
- int ch = h + (y - crtc->y) - cy;
-
- omap_connector_flush(connector, cx, cy, cw, ch);
- }
- }
-}
-
-#ifdef CONFIG_DEBUG_FS
-void omap_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m)
-{
- struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
- int i, n = drm_format_num_planes(fb->pixel_format);
-
- seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
- (char *)&fb->pixel_format);
-
- for (i = 0; i < n; i++) {
- struct plane *plane = &omap_fb->planes[i];
- seq_printf(m, " %d: offset=%d pitch=%d, obj: ",
- i, plane->offset, plane->pitch);
- omap_gem_describe(plane->bo, m);
- }
-}
-#endif
-
-struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
- struct drm_file *file, struct drm_mode_fb_cmd2 *mode_cmd)
-{
- struct drm_gem_object *bos[4];
- struct drm_framebuffer *fb;
- int ret;
-
- ret = objects_lookup(dev, file, mode_cmd->pixel_format,
- bos, mode_cmd->handles);
- if (ret)
- return ERR_PTR(ret);
-
- fb = omap_framebuffer_init(dev, mode_cmd, bos);
- if (IS_ERR(fb)) {
- int i, n = drm_format_num_planes(mode_cmd->pixel_format);
- for (i = 0; i < n; i++)
- drm_gem_object_unreference_unlocked(bos[i]);
- return fb;
- }
- return fb;
-}
-
-struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev,
- struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos)
-{
- struct omap_framebuffer *omap_fb;
- struct drm_framebuffer *fb = NULL;
- const struct format *format = NULL;
- int ret, i, n = drm_format_num_planes(mode_cmd->pixel_format);
-
- DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)",
- dev, mode_cmd, mode_cmd->width, mode_cmd->height,
- (char *)&mode_cmd->pixel_format);
-
- for (i = 0; i < ARRAY_SIZE(formats); i++) {
- if (formats[i].pixel_format == mode_cmd->pixel_format) {
- format = &formats[i];
- break;
- }
- }
-
- if (!format) {
- dev_err(dev->dev, "unsupported pixel format: %4.4s\n",
- (char *)&mode_cmd->pixel_format);
- ret = -EINVAL;
- goto fail;
- }
-
- omap_fb = kzalloc(sizeof(*omap_fb), GFP_KERNEL);
- if (!omap_fb) {
- ret = -ENOMEM;
- goto fail;
- }
-
- fb = &omap_fb->base;
- ret = drm_framebuffer_init(dev, fb, &omap_framebuffer_funcs);
- if (ret) {
- dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
- goto fail;
- }
-
- DBG("create: FB ID: %d (%p)", fb->base.id, fb);
-
- omap_fb->format = format;
-
- for (i = 0; i < n; i++) {
- struct plane *plane = &omap_fb->planes[i];
- int size, pitch = mode_cmd->pitches[i];
-
- if (pitch < (mode_cmd->width * format->planes[i].stride_bpp)) {
- dev_err(dev->dev, "provided buffer pitch is too small! %d < %d\n",
- pitch, mode_cmd->width * format->planes[i].stride_bpp);
- ret = -EINVAL;
- goto fail;
- }
-
- size = pitch * mode_cmd->height / format->planes[i].sub_y;
-
- if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
- dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
- bos[i]->size - mode_cmd->offsets[i], size);
- ret = -EINVAL;
- goto fail;
- }
-
- plane->bo = bos[i];
- plane->offset = mode_cmd->offsets[i];
- plane->pitch = pitch;
- plane->paddr = 0;
- }
-
- drm_helper_mode_fill_fb_struct(fb, mode_cmd);
-
- return fb;
-
-fail:
- if (fb)
- omap_framebuffer_destroy(fb);
-
- return ERR_PTR(ret);
-}
diff --git a/drivers/staging/omapdrm/omap_fbdev.c b/drivers/staging/omapdrm/omap_fbdev.c
deleted file mode 100644
index 70f2d6ed2ed..00000000000
--- a/drivers/staging/omapdrm/omap_fbdev.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_fbdev.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include "drm_crtc.h"
-#include "drm_fb_helper.h"
-
-MODULE_PARM_DESC(ywrap, "Enable ywrap scrolling (omap44xx and later, default 'y')");
-static bool ywrap_enabled = true;
-module_param_named(ywrap, ywrap_enabled, bool, 0644);
-
-/*
- * fbdev funcs, to implement legacy fbdev interface on top of drm driver
- */
-
-#define to_omap_fbdev(x) container_of(x, struct omap_fbdev, base)
-
-struct omap_fbdev {
- struct drm_fb_helper base;
- struct drm_framebuffer *fb;
- struct drm_gem_object *bo;
- bool ywrap_enabled;
-
- /* for deferred dmm roll when getting called in atomic ctx */
- struct work_struct work;
-};
-
-static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h);
-static struct drm_fb_helper *get_fb(struct fb_info *fbi);
-
-static ssize_t omap_fbdev_write(struct fb_info *fbi, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- ssize_t res;
-
- res = fb_sys_write(fbi, buf, count, ppos);
- omap_fbdev_flush(fbi, 0, 0, fbi->var.xres, fbi->var.yres);
-
- return res;
-}
-
-static void omap_fbdev_fillrect(struct fb_info *fbi,
- const struct fb_fillrect *rect)
-{
- sys_fillrect(fbi, rect);
- omap_fbdev_flush(fbi, rect->dx, rect->dy, rect->width, rect->height);
-}
-
-static void omap_fbdev_copyarea(struct fb_info *fbi,
- const struct fb_copyarea *area)
-{
- sys_copyarea(fbi, area);
- omap_fbdev_flush(fbi, area->dx, area->dy, area->width, area->height);
-}
-
-static void omap_fbdev_imageblit(struct fb_info *fbi,
- const struct fb_image *image)
-{
- sys_imageblit(fbi, image);
- omap_fbdev_flush(fbi, image->dx, image->dy,
- image->width, image->height);
-}
-
-static void pan_worker(struct work_struct *work)
-{
- struct omap_fbdev *fbdev = container_of(work, struct omap_fbdev, work);
- struct fb_info *fbi = fbdev->base.fbdev;
- int npages;
-
- /* DMM roll shifts in 4K pages: */
- npages = fbi->fix.line_length >> PAGE_SHIFT;
- omap_gem_roll(fbdev->bo, fbi->var.yoffset * npages);
-}
-
-static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *fbi)
-{
- struct drm_fb_helper *helper = get_fb(fbi);
- struct omap_fbdev *fbdev = to_omap_fbdev(helper);
-
- if (!helper)
- goto fallback;
-
- if (!fbdev->ywrap_enabled)
- goto fallback;
-
- if (drm_can_sleep()) {
- pan_worker(&fbdev->work);
- } else {
- struct omap_drm_private *priv = helper->dev->dev_private;
- queue_work(priv->wq, &fbdev->work);
- }
-
- return 0;
-
-fallback:
- return drm_fb_helper_pan_display(var, fbi);
-}
-
-static struct fb_ops omap_fb_ops = {
- .owner = THIS_MODULE,
-
- /* Note: to properly handle manual update displays, we wrap the
- * basic fbdev ops which write to the framebuffer
- */
- .fb_read = fb_sys_read,
- .fb_write = omap_fbdev_write,
- .fb_fillrect = omap_fbdev_fillrect,
- .fb_copyarea = omap_fbdev_copyarea,
- .fb_imageblit = omap_fbdev_imageblit,
-
- .fb_check_var = drm_fb_helper_check_var,
- .fb_set_par = drm_fb_helper_set_par,
- .fb_pan_display = omap_fbdev_pan_display,
- .fb_blank = drm_fb_helper_blank,
- .fb_setcmap = drm_fb_helper_setcmap,
-
- .fb_debug_enter = drm_fb_helper_debug_enter,
- .fb_debug_leave = drm_fb_helper_debug_leave,
-};
-
-static int omap_fbdev_create(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct omap_fbdev *fbdev = to_omap_fbdev(helper);
- struct drm_device *dev = helper->dev;
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_framebuffer *fb = NULL;
- union omap_gem_size gsize;
- struct fb_info *fbi = NULL;
- struct drm_mode_fb_cmd2 mode_cmd = {0};
- dma_addr_t paddr;
- int ret;
-
- /* only doing ARGB32 since this is what is needed to alpha-blend
- * with video overlays:
- */
- sizes->surface_bpp = 32;
- sizes->surface_depth = 32;
-
- DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
- sizes->surface_height, sizes->surface_bpp,
- sizes->fb_width, sizes->fb_height);
-
- mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
- sizes->surface_depth);
-
- mode_cmd.width = sizes->surface_width;
- mode_cmd.height = sizes->surface_height;
-
- mode_cmd.pitches[0] = align_pitch(
- mode_cmd.width * ((sizes->surface_bpp + 7) / 8),
- mode_cmd.width, sizes->surface_bpp);
-
- fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled;
- if (fbdev->ywrap_enabled) {
- /* need to align pitch to page size if using DMM scrolling */
- mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE);
- }
-
- /* allocate backing bo */
- gsize = (union omap_gem_size){
- .bytes = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height),
- };
- DBG("allocating %d bytes for fb %d", gsize.bytes, dev->primary->index);
- fbdev->bo = omap_gem_new(dev, gsize, OMAP_BO_SCANOUT | OMAP_BO_WC);
- if (!fbdev->bo) {
- dev_err(dev->dev, "failed to allocate buffer object\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- fb = omap_framebuffer_init(dev, &mode_cmd, &fbdev->bo);
- if (IS_ERR(fb)) {
- dev_err(dev->dev, "failed to allocate fb\n");
- /* note: if fb creation failed, we can't rely on fb destroy
- * to unref the bo:
- */
- drm_gem_object_unreference(fbdev->bo);
- ret = PTR_ERR(fb);
- goto fail;
- }
-
- /* note: this keeps the bo pinned.. which is perhaps not ideal,
- * but is needed as long as we use fb_mmap() to mmap to userspace
- * (since this happens using fix.smem_start). Possibly we could
- * implement our own mmap using GEM mmap support to avoid this
- * (non-tiled buffer doesn't need to be pinned for fbcon to write
- * to it). Then we just need to be sure that we are able to re-
- * pin it in case of an opps.
- */
- ret = omap_gem_get_paddr(fbdev->bo, &paddr, true);
- if (ret) {
- dev_err(dev->dev,
- "could not map (paddr)! Skipping framebuffer alloc\n");
- ret = -ENOMEM;
- goto fail;
- }
-
- mutex_lock(&dev->struct_mutex);
-
- fbi = framebuffer_alloc(0, dev->dev);
- if (!fbi) {
- dev_err(dev->dev, "failed to allocate fb info\n");
- ret = -ENOMEM;
- goto fail_unlock;
- }
-
- DBG("fbi=%p, dev=%p", fbi, dev);
-
- fbdev->fb = fb;
- helper->fb = fb;
- helper->fbdev = fbi;
-
- fbi->par = helper;
- fbi->flags = FBINFO_DEFAULT;
- fbi->fbops = &omap_fb_ops;
-
- strcpy(fbi->fix.id, MODULE_NAME);
-
- ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
- if (ret) {
- ret = -ENOMEM;
- goto fail_unlock;
- }
-
- drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
- drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
-
- dev->mode_config.fb_base = paddr;
-
- fbi->screen_base = omap_gem_vaddr(fbdev->bo);
- fbi->screen_size = fbdev->bo->size;
- fbi->fix.smem_start = paddr;
- fbi->fix.smem_len = fbdev->bo->size;
-
- /* if we have DMM, then we can use it for scrolling by just
- * shuffling pages around in DMM rather than doing sw blit.
- */
- if (fbdev->ywrap_enabled) {
- DRM_INFO("Enabling DMM ywrap scrolling\n");
- fbi->flags |= FBINFO_HWACCEL_YWRAP | FBINFO_READS_FAST;
- fbi->fix.ywrapstep = 1;
- }
-
-
- DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres);
- DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height);
-
- mutex_unlock(&dev->struct_mutex);
-
- return 0;
-
-fail_unlock:
- mutex_unlock(&dev->struct_mutex);
-fail:
-
- if (ret) {
- if (fbi)
- framebuffer_release(fbi);
- if (fb)
- drm_framebuffer_remove(fb);
- }
-
- return ret;
-}
-
-static void omap_crtc_fb_gamma_set(struct drm_crtc *crtc,
- u16 red, u16 green, u16 blue, int regno)
-{
- DBG("fbdev: set gamma");
-}
-
-static void omap_crtc_fb_gamma_get(struct drm_crtc *crtc,
- u16 *red, u16 *green, u16 *blue, int regno)
-{
- DBG("fbdev: get gamma");
-}
-
-static int omap_fbdev_probe(struct drm_fb_helper *helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- int new_fb = 0;
- int ret;
-
- if (!helper->fb) {
- ret = omap_fbdev_create(helper, sizes);
- if (ret)
- return ret;
- new_fb = 1;
- }
- return new_fb;
-}
-
-static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
- .gamma_set = omap_crtc_fb_gamma_set,
- .gamma_get = omap_crtc_fb_gamma_get,
- .fb_probe = omap_fbdev_probe,
-};
-
-static struct drm_fb_helper *get_fb(struct fb_info *fbi)
-{
- if (!fbi || strcmp(fbi->fix.id, MODULE_NAME)) {
- /* these are not the fb's you're looking for */
- return NULL;
- }
- return fbi->par;
-}
-
-/* flush an area of the framebuffer (in case of manual update display that
- * is not automatically flushed)
- */
-static void omap_fbdev_flush(struct fb_info *fbi, int x, int y, int w, int h)
-{
- struct drm_fb_helper *helper = get_fb(fbi);
-
- if (!helper)
- return;
-
- VERB("flush fbdev: %d,%d %dx%d, fbi=%p", x, y, w, h, fbi);
-
- omap_framebuffer_flush(helper->fb, x, y, w, h);
-}
-
-/* initialize fbdev helper */
-struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_fbdev *fbdev = NULL;
- struct drm_fb_helper *helper;
- int ret = 0;
-
- fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
- if (!fbdev)
- goto fail;
-
- INIT_WORK(&fbdev->work, pan_worker);
-
- helper = &fbdev->base;
-
- helper->funcs = &omap_fb_helper_funcs;
-
- ret = drm_fb_helper_init(dev, helper,
- priv->num_crtcs, priv->num_connectors);
- if (ret) {
- dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
- goto fail;
- }
-
- drm_fb_helper_single_add_all_connectors(helper);
- drm_fb_helper_initial_config(helper, 32);
-
- priv->fbdev = helper;
-
- return helper;
-
-fail:
- kfree(fbdev);
- return NULL;
-}
-
-void omap_fbdev_free(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_fb_helper *helper = priv->fbdev;
- struct omap_fbdev *fbdev;
- struct fb_info *fbi;
-
- DBG();
-
- fbi = helper->fbdev;
-
- /* only cleanup framebuffer if it is present */
- if (fbi) {
- unregister_framebuffer(fbi);
- framebuffer_release(fbi);
- }
-
- drm_fb_helper_fini(helper);
-
- fbdev = to_omap_fbdev(priv->fbdev);
-
- /* this will free the backing object */
- if (fbdev->fb)
- drm_framebuffer_remove(fbdev->fb);
-
- kfree(fbdev);
-
- priv->fbdev = NULL;
-}
diff --git a/drivers/staging/omapdrm/omap_gem.c b/drivers/staging/omapdrm/omap_gem.c
deleted file mode 100644
index 518d03d4d4f..00000000000
--- a/drivers/staging/omapdrm/omap_gem.c
+++ /dev/null
@@ -1,1507 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_gem.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include <linux/spinlock.h>
-#include <linux/shmem_fs.h>
-
-#include "omap_drv.h"
-#include "omap_dmm_tiler.h"
-
-/* remove these once drm core helpers are merged */
-struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
-void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
- bool dirty, bool accessed);
-int _drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size);
-
-/*
- * GEM buffer object implementation.
- */
-
-#define to_omap_bo(x) container_of(x, struct omap_gem_object, base)
-
-/* note: we use upper 8 bits of flags for driver-internal flags: */
-#define OMAP_BO_DMA 0x01000000 /* actually is physically contiguous */
-#define OMAP_BO_EXT_SYNC 0x02000000 /* externally allocated sync object */
-#define OMAP_BO_EXT_MEM 0x04000000 /* externally allocated memory */
-
-
-struct omap_gem_object {
- struct drm_gem_object base;
-
- struct list_head mm_list;
-
- uint32_t flags;
-
- /** width/height for tiled formats (rounded up to slot boundaries) */
- uint16_t width, height;
-
- /** roll applied when mapping to DMM */
- uint32_t roll;
-
- /**
- * If buffer is allocated physically contiguous, the OMAP_BO_DMA flag
- * is set and the paddr is valid. Also if the buffer is remapped in
- * TILER and paddr_cnt > 0, then paddr is valid. But if you are using
- * the physical address and OMAP_BO_DMA is not set, then you should
- * be going thru omap_gem_{get,put}_paddr() to ensure the mapping is
- * not removed from under your feet.
- *
- * Note that OMAP_BO_SCANOUT is a hint from userspace that DMA capable
- * buffer is requested, but doesn't mean that it is. Use the
- * OMAP_BO_DMA flag to determine if the buffer has a DMA capable
- * physical address.
- */
- dma_addr_t paddr;
-
- /**
- * # of users of paddr
- */
- uint32_t paddr_cnt;
-
- /**
- * tiler block used when buffer is remapped in DMM/TILER.
- */
- struct tiler_block *block;
-
- /**
- * Array of backing pages, if allocated. Note that pages are never
- * allocated for buffers originally allocated from contiguous memory
- */
- struct page **pages;
-
- /** addresses corresponding to pages in above array */
- dma_addr_t *addrs;
-
- /**
- * Virtual address, if mapped.
- */
- void *vaddr;
-
- /**
- * sync-object allocated on demand (if needed)
- *
- * Per-buffer sync-object for tracking pending and completed hw/dma
- * read and write operations. The layout in memory is dictated by
- * the SGX firmware, which uses this information to stall the command
- * stream if a surface is not ready yet.
- *
- * Note that when buffer is used by SGX, the sync-object needs to be
- * allocated from a special heap of sync-objects. This way many sync
- * objects can be packed in a page, and not waste GPU virtual address
- * space. Because of this we have to have a omap_gem_set_sync_object()
- * API to allow replacement of the syncobj after it has (potentially)
- * already been allocated. A bit ugly but I haven't thought of a
- * better alternative.
- */
- struct {
- uint32_t write_pending;
- uint32_t write_complete;
- uint32_t read_pending;
- uint32_t read_complete;
- } *sync;
-};
-
-static int get_pages(struct drm_gem_object *obj, struct page ***pages);
-static uint64_t mmap_offset(struct drm_gem_object *obj);
-
-/* To deal with userspace mmap'ings of 2d tiled buffers, which (a) are
- * not necessarily pinned in TILER all the time, and (b) when they are
- * they are not necessarily page aligned, we reserve one or more small
- * regions in each of the 2d containers to use as a user-GART where we
- * can create a second page-aligned mapping of parts of the buffer
- * being accessed from userspace.
- *
- * Note that we could optimize slightly when we know that multiple
- * tiler containers are backed by the same PAT.. but I'll leave that
- * for later..
- */
-#define NUM_USERGART_ENTRIES 2
-struct usergart_entry {
- struct tiler_block *block; /* the reserved tiler block */
- dma_addr_t paddr;
- struct drm_gem_object *obj; /* the current pinned obj */
- pgoff_t obj_pgoff; /* page offset of obj currently
- mapped in */
-};
-static struct {
- struct usergart_entry entry[NUM_USERGART_ENTRIES];
- int height; /* height in rows */
- int height_shift; /* ilog2(height in rows) */
- int slot_shift; /* ilog2(width per slot) */
- int stride_pfn; /* stride in pages */
- int last; /* index of last used entry */
-} *usergart;
-
-static void evict_entry(struct drm_gem_object *obj,
- enum tiler_fmt fmt, struct usergart_entry *entry)
-{
- if (obj->dev->dev_mapping) {
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int n = usergart[fmt].height;
- size_t size = PAGE_SIZE * n;
- loff_t off = mmap_offset(obj) +
- (entry->obj_pgoff << PAGE_SHIFT);
- const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE);
- if (m > 1) {
- int i;
- /* if stride > than PAGE_SIZE then sparse mapping: */
- for (i = n; i > 0; i--) {
- unmap_mapping_range(obj->dev->dev_mapping,
- off, PAGE_SIZE, 1);
- off += PAGE_SIZE * m;
- }
- } else {
- unmap_mapping_range(obj->dev->dev_mapping, off, size, 1);
- }
- }
-
- entry->obj = NULL;
-}
-
-/* Evict a buffer from usergart, if it is mapped there */
-static void evict(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- if (omap_obj->flags & OMAP_BO_TILED) {
- enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
- int i;
-
- if (!usergart)
- return;
-
- for (i = 0; i < NUM_USERGART_ENTRIES; i++) {
- struct usergart_entry *entry = &usergart[fmt].entry[i];
- if (entry->obj == obj)
- evict_entry(obj, fmt, entry);
- }
- }
-}
-
-/* GEM objects can either be allocated from contiguous memory (in which
- * case obj->filp==NULL), or w/ shmem backing (obj->filp!=NULL). But non
- * contiguous buffers can be remapped in TILER/DMM if they need to be
- * contiguous... but we don't do this all the time to reduce pressure
- * on TILER/DMM space when we know at allocation time that the buffer
- * will need to be scanned out.
- */
-static inline bool is_shmem(struct drm_gem_object *obj)
-{
- return obj->filp != NULL;
-}
-
-/**
- * shmem buffers that are mapped cached can simulate coherency via using
- * page faulting to keep track of dirty pages
- */
-static inline bool is_cached_coherent(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- return is_shmem(obj) &&
- ((omap_obj->flags & OMAP_BO_CACHE_MASK) == OMAP_BO_CACHED);
-}
-
-static DEFINE_SPINLOCK(sync_lock);
-
-/** ensure backing pages are allocated */
-static int omap_gem_attach_pages(struct drm_gem_object *obj)
-{
- struct drm_device *dev = obj->dev;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- struct page **pages;
- int npages = obj->size >> PAGE_SHIFT;
- int i, ret;
- dma_addr_t *addrs;
-
- WARN_ON(omap_obj->pages);
-
- /* TODO: __GFP_DMA32 .. but somehow GFP_HIGHMEM is coming from the
- * mapping_gfp_mask(mapping) which conflicts w/ GFP_DMA32.. probably
- * we actually want CMA memory for it all anyways..
- */
- pages = _drm_gem_get_pages(obj, GFP_KERNEL);
- if (IS_ERR(pages)) {
- dev_err(obj->dev->dev, "could not get pages: %ld\n", PTR_ERR(pages));
- return PTR_ERR(pages);
- }
-
- /* for non-cached buffers, ensure the new pages are clean because
- * DSS, GPU, etc. are not cache coherent:
- */
- if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
- addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
- if (!addrs) {
- ret = -ENOMEM;
- goto free_pages;
- }
-
- for (i = 0; i < npages; i++) {
- addrs[i] = dma_map_page(dev->dev, pages[i],
- 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
- }
- } else {
- addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
- if (!addrs) {
- ret = -ENOMEM;
- goto free_pages;
- }
- }
-
- omap_obj->addrs = addrs;
- omap_obj->pages = pages;
-
- return 0;
-
-free_pages:
- _drm_gem_put_pages(obj, pages, true, false);
-
- return ret;
-}
-
-/** release backing pages */
-static void omap_gem_detach_pages(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- /* for non-cached buffers, ensure the new pages are clean because
- * DSS, GPU, etc. are not cache coherent:
- */
- if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
- int i, npages = obj->size >> PAGE_SHIFT;
- for (i = 0; i < npages; i++) {
- dma_unmap_page(obj->dev->dev, omap_obj->addrs[i],
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- }
- }
-
- kfree(omap_obj->addrs);
- omap_obj->addrs = NULL;
-
- _drm_gem_put_pages(obj, omap_obj->pages, true, false);
- omap_obj->pages = NULL;
-}
-
-/* get buffer flags */
-uint32_t omap_gem_flags(struct drm_gem_object *obj)
-{
- return to_omap_bo(obj)->flags;
-}
-
-/** get mmap offset */
-static uint64_t mmap_offset(struct drm_gem_object *obj)
-{
- struct drm_device *dev = obj->dev;
-
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
- if (!obj->map_list.map) {
- /* Make it mmapable */
- size_t size = omap_gem_mmap_size(obj);
- int ret = _drm_gem_create_mmap_offset_size(obj, size);
-
- if (ret) {
- dev_err(dev->dev, "could not allocate mmap offset\n");
- return 0;
- }
- }
-
- return (uint64_t)obj->map_list.hash.key << PAGE_SHIFT;
-}
-
-uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj)
-{
- uint64_t offset;
- mutex_lock(&obj->dev->struct_mutex);
- offset = mmap_offset(obj);
- mutex_unlock(&obj->dev->struct_mutex);
- return offset;
-}
-
-/** get mmap size */
-size_t omap_gem_mmap_size(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- size_t size = obj->size;
-
- if (omap_obj->flags & OMAP_BO_TILED) {
- /* for tiled buffers, the virtual size has stride rounded up
- * to 4kb.. (to hide the fact that row n+1 might start 16kb or
- * 32kb later!). But we don't back the entire buffer with
- * pages, only the valid picture part.. so need to adjust for
- * this in the size used to mmap and generate mmap offset
- */
- size = tiler_vsize(gem2fmt(omap_obj->flags),
- omap_obj->width, omap_obj->height);
- }
-
- return size;
-}
-
-/* get tiled size, returns -EINVAL if not tiled buffer */
-int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- if (omap_obj->flags & OMAP_BO_TILED) {
- *w = omap_obj->width;
- *h = omap_obj->height;
- return 0;
- }
- return -EINVAL;
-}
-
-/* Normal handling for the case of faulting in non-tiled buffers */
-static int fault_1d(struct drm_gem_object *obj,
- struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- unsigned long pfn;
- pgoff_t pgoff;
-
- /* We don't use vmf->pgoff since that has the fake offset: */
- pgoff = ((unsigned long)vmf->virtual_address -
- vma->vm_start) >> PAGE_SHIFT;
-
- if (omap_obj->pages) {
- omap_gem_cpu_sync(obj, pgoff);
- pfn = page_to_pfn(omap_obj->pages[pgoff]);
- } else {
- BUG_ON(!(omap_obj->flags & OMAP_BO_DMA));
- pfn = (omap_obj->paddr >> PAGE_SHIFT) + pgoff;
- }
-
- VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
- pfn, pfn << PAGE_SHIFT);
-
- return vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
-}
-
-/* Special handling for the case of faulting in 2d tiled buffers */
-static int fault_2d(struct drm_gem_object *obj,
- struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- struct usergart_entry *entry;
- enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
- struct page *pages[64]; /* XXX is this too much to have on stack? */
- unsigned long pfn;
- pgoff_t pgoff, base_pgoff;
- void __user *vaddr;
- int i, ret, slots;
-
- /*
- * Note the height of the slot is also equal to the number of pages
- * that need to be mapped in to fill 4kb wide CPU page. If the slot
- * height is 64, then 64 pages fill a 4kb wide by 64 row region.
- */
- const int n = usergart[fmt].height;
- const int n_shift = usergart[fmt].height_shift;
-
- /*
- * If buffer width in bytes > PAGE_SIZE then the virtual stride is
- * rounded up to next multiple of PAGE_SIZE.. this need to be taken
- * into account in some of the math, so figure out virtual stride
- * in pages
- */
- const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE);
-
- /* We don't use vmf->pgoff since that has the fake offset: */
- pgoff = ((unsigned long)vmf->virtual_address -
- vma->vm_start) >> PAGE_SHIFT;
-
- /*
- * Actual address we start mapping at is rounded down to previous slot
- * boundary in the y direction:
- */
- base_pgoff = round_down(pgoff, m << n_shift);
-
- /* figure out buffer width in slots */
- slots = omap_obj->width >> usergart[fmt].slot_shift;
-
- vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
-
- entry = &usergart[fmt].entry[usergart[fmt].last];
-
- /* evict previous buffer using this usergart entry, if any: */
- if (entry->obj)
- evict_entry(entry->obj, fmt, entry);
-
- entry->obj = obj;
- entry->obj_pgoff = base_pgoff;
-
- /* now convert base_pgoff to phys offset from virt offset: */
- base_pgoff = (base_pgoff >> n_shift) * slots;
-
- /* for wider-than 4k.. figure out which part of the slot-row we want: */
- if (m > 1) {
- int off = pgoff % m;
- entry->obj_pgoff += off;
- base_pgoff /= m;
- slots = min(slots - (off << n_shift), n);
- base_pgoff += off << n_shift;
- vaddr += off << PAGE_SHIFT;
- }
-
- /*
- * Map in pages. Beyond the valid pixel part of the buffer, we set
- * pages[i] to NULL to get a dummy page mapped in.. if someone
- * reads/writes it they will get random/undefined content, but at
- * least it won't be corrupting whatever other random page used to
- * be mapped in, or other undefined behavior.
- */
- memcpy(pages, &omap_obj->pages[base_pgoff],
- sizeof(struct page *) * slots);
- memset(pages + slots, 0,
- sizeof(struct page *) * (n - slots));
-
- ret = tiler_pin(entry->block, pages, ARRAY_SIZE(pages), 0, true);
- if (ret) {
- dev_err(obj->dev->dev, "failed to pin: %d\n", ret);
- return ret;
- }
-
- pfn = entry->paddr >> PAGE_SHIFT;
-
- VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
- pfn, pfn << PAGE_SHIFT);
-
- for (i = n; i > 0; i--) {
- vm_insert_mixed(vma, (unsigned long)vaddr, pfn);
- pfn += usergart[fmt].stride_pfn;
- vaddr += PAGE_SIZE * m;
- }
-
- /* simple round-robin: */
- usergart[fmt].last = (usergart[fmt].last + 1) % NUM_USERGART_ENTRIES;
-
- return 0;
-}
-
-/**
- * omap_gem_fault - pagefault handler for GEM objects
- * @vma: the VMA of the GEM object
- * @vmf: fault detail
- *
- * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
- * does most of the work for us including the actual map/unmap calls
- * but we need to do the actual page work.
- *
- * The VMA was set up by GEM. In doing so it also ensured that the
- * vma->vm_private_data points to the GEM object that is backing this
- * mapping.
- */
-int omap_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- struct drm_gem_object *obj = vma->vm_private_data;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- struct drm_device *dev = obj->dev;
- struct page **pages;
- int ret;
-
- /* Make sure we don't parallel update on a fault, nor move or remove
- * something from beneath our feet
- */
- mutex_lock(&dev->struct_mutex);
-
- /* if a shmem backed object, make sure we have pages attached now */
- ret = get_pages(obj, &pages);
- if (ret)
- goto fail;
-
- /* where should we do corresponding put_pages().. we are mapping
- * the original page, rather than thru a GART, so we can't rely
- * on eviction to trigger this. But munmap() or all mappings should
- * probably trigger put_pages()?
- */
-
- if (omap_obj->flags & OMAP_BO_TILED)
- ret = fault_2d(obj, vma, vmf);
- else
- ret = fault_1d(obj, vma, vmf);
-
-
-fail:
- mutex_unlock(&dev->struct_mutex);
- switch (ret) {
- case 0:
- case -ERESTARTSYS:
- case -EINTR:
- return VM_FAULT_NOPAGE;
- case -ENOMEM:
- return VM_FAULT_OOM;
- default:
- return VM_FAULT_SIGBUS;
- }
-}
-
-/** We override mainly to fix up some of the vm mapping flags.. */
-int omap_gem_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- int ret;
-
- ret = drm_gem_mmap(filp, vma);
- if (ret) {
- DBG("mmap failed: %d", ret);
- return ret;
- }
-
- return omap_gem_mmap_obj(vma->vm_private_data, vma);
-}
-
-int omap_gem_mmap_obj(struct drm_gem_object *obj,
- struct vm_area_struct *vma)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- vma->vm_flags &= ~VM_PFNMAP;
- vma->vm_flags |= VM_MIXEDMAP;
-
- if (omap_obj->flags & OMAP_BO_WC) {
- vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
- } else if (omap_obj->flags & OMAP_BO_UNCACHED) {
- vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags));
- } else {
- /*
- * We do have some private objects, at least for scanout buffers
- * on hardware without DMM/TILER. But these are allocated write-
- * combine
- */
- if (WARN_ON(!obj->filp))
- return -EINVAL;
-
- /*
- * Shunt off cached objs to shmem file so they have their own
- * address_space (so unmap_mapping_range does what we want,
- * in particular in the case of mmap'd dmabufs)
- */
- fput(vma->vm_file);
- vma->vm_pgoff = 0;
- vma->vm_file = get_file(obj->filp);
-
- vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- }
-
- return 0;
-}
-
-
-/**
- * omap_gem_dumb_create - create a dumb buffer
- * @drm_file: our client file
- * @dev: our device
- * @args: the requested arguments copied from userspace
- *
- * Allocate a buffer suitable for use for a frame buffer of the
- * form described by user space. Give userspace a handle by which
- * to reference it.
- */
-int omap_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args)
-{
- union omap_gem_size gsize;
-
- /* in case someone tries to feed us a completely bogus stride: */
- args->pitch = align_pitch(args->pitch, args->width, args->bpp);
- args->size = PAGE_ALIGN(args->pitch * args->height);
-
- gsize = (union omap_gem_size){
- .bytes = args->size,
- };
-
- return omap_gem_new_handle(dev, file, gsize,
- OMAP_BO_SCANOUT | OMAP_BO_WC, &args->handle);
-}
-
-/**
- * omap_gem_dumb_destroy - destroy a dumb buffer
- * @file: client file
- * @dev: our DRM device
- * @handle: the object handle
- *
- * Destroy a handle that was created via omap_gem_dumb_create.
- */
-int omap_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle)
-{
- /* No special work needed, drop the reference and see what falls out */
- return drm_gem_handle_delete(file, handle);
-}
-
-/**
- * omap_gem_dumb_map - buffer mapping for dumb interface
- * @file: our drm client file
- * @dev: drm device
- * @handle: GEM handle to the object (from dumb_create)
- *
- * Do the necessary setup to allow the mapping of the frame buffer
- * into user memory. We don't have to do much here at the moment.
- */
-int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset)
-{
- struct drm_gem_object *obj;
- int ret = 0;
-
- /* GEM does all our handle to object mapping */
- obj = drm_gem_object_lookup(dev, file, handle);
- if (obj == NULL) {
- ret = -ENOENT;
- goto fail;
- }
-
- *offset = omap_gem_mmap_offset(obj);
-
- drm_gem_object_unreference_unlocked(obj);
-
-fail:
- return ret;
-}
-
-/* Set scrolling position. This allows us to implement fast scrolling
- * for console.
- *
- * Call only from non-atomic contexts.
- */
-int omap_gem_roll(struct drm_gem_object *obj, uint32_t roll)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- uint32_t npages = obj->size >> PAGE_SHIFT;
- int ret = 0;
-
- if (roll > npages) {
- dev_err(obj->dev->dev, "invalid roll: %d\n", roll);
- return -EINVAL;
- }
-
- omap_obj->roll = roll;
-
- mutex_lock(&obj->dev->struct_mutex);
-
- /* if we aren't mapped yet, we don't need to do anything */
- if (omap_obj->block) {
- struct page **pages;
- ret = get_pages(obj, &pages);
- if (ret)
- goto fail;
- ret = tiler_pin(omap_obj->block, pages, npages, roll, true);
- if (ret)
- dev_err(obj->dev->dev, "could not repin: %d\n", ret);
- }
-
-fail:
- mutex_unlock(&obj->dev->struct_mutex);
-
- return ret;
-}
-
-/* Sync the buffer for CPU access.. note pages should already be
- * attached, ie. omap_gem_get_pages()
- */
-void omap_gem_cpu_sync(struct drm_gem_object *obj, int pgoff)
-{
- struct drm_device *dev = obj->dev;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- if (is_cached_coherent(obj) && omap_obj->addrs[pgoff]) {
- dma_unmap_page(dev->dev, omap_obj->addrs[pgoff],
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- omap_obj->addrs[pgoff] = 0;
- }
-}
-
-/* sync the buffer for DMA access */
-void omap_gem_dma_sync(struct drm_gem_object *obj,
- enum dma_data_direction dir)
-{
- struct drm_device *dev = obj->dev;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- if (is_cached_coherent(obj)) {
- int i, npages = obj->size >> PAGE_SHIFT;
- struct page **pages = omap_obj->pages;
- bool dirty = false;
-
- for (i = 0; i < npages; i++) {
- if (!omap_obj->addrs[i]) {
- omap_obj->addrs[i] = dma_map_page(dev->dev, pages[i], 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- dirty = true;
- }
- }
-
- if (dirty) {
- unmap_mapping_range(obj->filp->f_mapping, 0,
- omap_gem_mmap_size(obj), 1);
- }
- }
-}
-
-/* Get physical address for DMA.. if 'remap' is true, and the buffer is not
- * already contiguous, remap it to pin in physically contiguous memory.. (ie.
- * map in TILER)
- */
-int omap_gem_get_paddr(struct drm_gem_object *obj,
- dma_addr_t *paddr, bool remap)
-{
- struct omap_drm_private *priv = obj->dev->dev_private;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
-
- mutex_lock(&obj->dev->struct_mutex);
-
- if (remap && is_shmem(obj) && priv->has_dmm) {
- if (omap_obj->paddr_cnt == 0) {
- struct page **pages;
- uint32_t npages = obj->size >> PAGE_SHIFT;
- enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
- struct tiler_block *block;
-
- BUG_ON(omap_obj->block);
-
- ret = get_pages(obj, &pages);
- if (ret)
- goto fail;
-
- if (omap_obj->flags & OMAP_BO_TILED) {
- block = tiler_reserve_2d(fmt,
- omap_obj->width,
- omap_obj->height, 0);
- } else {
- block = tiler_reserve_1d(obj->size);
- }
-
- if (IS_ERR(block)) {
- ret = PTR_ERR(block);
- dev_err(obj->dev->dev,
- "could not remap: %d (%d)\n", ret, fmt);
- goto fail;
- }
-
- /* TODO: enable async refill.. */
- ret = tiler_pin(block, pages, npages,
- omap_obj->roll, true);
- if (ret) {
- tiler_release(block);
- dev_err(obj->dev->dev,
- "could not pin: %d\n", ret);
- goto fail;
- }
-
- omap_obj->paddr = tiler_ssptr(block);
- omap_obj->block = block;
-
- DBG("got paddr: %08x", omap_obj->paddr);
- }
-
- omap_obj->paddr_cnt++;
-
- *paddr = omap_obj->paddr;
- } else if (omap_obj->flags & OMAP_BO_DMA) {
- *paddr = omap_obj->paddr;
- } else {
- ret = -EINVAL;
- goto fail;
- }
-
-fail:
- mutex_unlock(&obj->dev->struct_mutex);
-
- return ret;
-}
-
-/* Release physical address, when DMA is no longer being performed.. this
- * could potentially unpin and unmap buffers from TILER
- */
-int omap_gem_put_paddr(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
-
- mutex_lock(&obj->dev->struct_mutex);
- if (omap_obj->paddr_cnt > 0) {
- omap_obj->paddr_cnt--;
- if (omap_obj->paddr_cnt == 0) {
- ret = tiler_unpin(omap_obj->block);
- if (ret) {
- dev_err(obj->dev->dev,
- "could not unpin pages: %d\n", ret);
- goto fail;
- }
- ret = tiler_release(omap_obj->block);
- if (ret) {
- dev_err(obj->dev->dev,
- "could not release unmap: %d\n", ret);
- }
- omap_obj->block = NULL;
- }
- }
-fail:
- mutex_unlock(&obj->dev->struct_mutex);
- return ret;
-}
-
-/* Get rotated scanout address (only valid if already pinned), at the
- * specified orientation and x,y offset from top-left corner of buffer
- * (only valid for tiled 2d buffers)
- */
-int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient,
- int x, int y, dma_addr_t *paddr)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = -EINVAL;
-
- mutex_lock(&obj->dev->struct_mutex);
- if ((omap_obj->paddr_cnt > 0) && omap_obj->block &&
- (omap_obj->flags & OMAP_BO_TILED)) {
- *paddr = tiler_tsptr(omap_obj->block, orient, x, y);
- ret = 0;
- }
- mutex_unlock(&obj->dev->struct_mutex);
- return ret;
-}
-
-/* Get tiler stride for the buffer (only valid for 2d tiled buffers) */
-int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = -EINVAL;
- if (omap_obj->flags & OMAP_BO_TILED)
- ret = tiler_stride(gem2fmt(omap_obj->flags), orient);
- return ret;
-}
-
-/* acquire pages when needed (for example, for DMA where physically
- * contiguous buffer is not required
- */
-static int get_pages(struct drm_gem_object *obj, struct page ***pages)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
-
- if (is_shmem(obj) && !omap_obj->pages) {
- ret = omap_gem_attach_pages(obj);
- if (ret) {
- dev_err(obj->dev->dev, "could not attach pages\n");
- return ret;
- }
- }
-
- /* TODO: even phys-contig.. we should have a list of pages? */
- *pages = omap_obj->pages;
-
- return 0;
-}
-
-/* if !remap, and we don't have pages backing, then fail, rather than
- * increasing the pin count (which we don't really do yet anyways,
- * because we don't support swapping pages back out). And 'remap'
- * might not be quite the right name, but I wanted to keep it working
- * similarly to omap_gem_get_paddr(). Note though that mutex is not
- * aquired if !remap (because this can be called in atomic ctxt),
- * but probably omap_gem_get_paddr() should be changed to work in the
- * same way. If !remap, a matching omap_gem_put_pages() call is not
- * required (and should not be made).
- */
-int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages,
- bool remap)
-{
- int ret;
- if (!remap) {
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- if (!omap_obj->pages)
- return -ENOMEM;
- *pages = omap_obj->pages;
- return 0;
- }
- mutex_lock(&obj->dev->struct_mutex);
- ret = get_pages(obj, pages);
- mutex_unlock(&obj->dev->struct_mutex);
- return ret;
-}
-
-/* release pages when DMA no longer being performed */
-int omap_gem_put_pages(struct drm_gem_object *obj)
-{
- /* do something here if we dynamically attach/detach pages.. at
- * least they would no longer need to be pinned if everyone has
- * released the pages..
- */
- return 0;
-}
-
-/* Get kernel virtual address for CPU access.. this more or less only
- * exists for omap_fbdev. This should be called with struct_mutex
- * held.
- */
-void *omap_gem_vaddr(struct drm_gem_object *obj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
- if (!omap_obj->vaddr) {
- struct page **pages;
- int ret = get_pages(obj, &pages);
- if (ret)
- return ERR_PTR(ret);
- omap_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
- VM_MAP, pgprot_writecombine(PAGE_KERNEL));
- }
- return omap_obj->vaddr;
-}
-
-#ifdef CONFIG_PM
-/* re-pin objects in DMM in resume path: */
-int omap_gem_resume(struct device *dev)
-{
- struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct omap_drm_private *priv = drm_dev->dev_private;
- struct omap_gem_object *omap_obj;
- int ret = 0;
-
- list_for_each_entry(omap_obj, &priv->obj_list, mm_list) {
- if (omap_obj->block) {
- struct drm_gem_object *obj = &omap_obj->base;
- uint32_t npages = obj->size >> PAGE_SHIFT;
- WARN_ON(!omap_obj->pages); /* this can't happen */
- ret = tiler_pin(omap_obj->block,
- omap_obj->pages, npages,
- omap_obj->roll, true);
- if (ret) {
- dev_err(dev, "could not repin: %d\n", ret);
- return ret;
- }
- }
- }
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_DEBUG_FS
-void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
-{
- struct drm_device *dev = obj->dev;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- uint64_t off = 0;
-
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
- if (obj->map_list.map)
- off = (uint64_t)obj->map_list.hash.key;
-
- seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
- omap_obj->flags, obj->name, obj->refcount.refcount.counter,
- off, omap_obj->paddr, omap_obj->paddr_cnt,
- omap_obj->vaddr, omap_obj->roll);
-
- if (omap_obj->flags & OMAP_BO_TILED) {
- seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height);
- if (omap_obj->block) {
- struct tcm_area *area = &omap_obj->block->area;
- seq_printf(m, " (%dx%d, %dx%d)",
- area->p0.x, area->p0.y,
- area->p1.x, area->p1.y);
- }
- } else {
- seq_printf(m, " %d", obj->size);
- }
-
- seq_printf(m, "\n");
-}
-
-void omap_gem_describe_objects(struct list_head *list, struct seq_file *m)
-{
- struct omap_gem_object *omap_obj;
- int count = 0;
- size_t size = 0;
-
- list_for_each_entry(omap_obj, list, mm_list) {
- struct drm_gem_object *obj = &omap_obj->base;
- seq_printf(m, " ");
- omap_gem_describe(obj, m);
- count++;
- size += obj->size;
- }
-
- seq_printf(m, "Total %d objects, %zu bytes\n", count, size);
-}
-#endif
-
-/* Buffer Synchronization:
- */
-
-struct omap_gem_sync_waiter {
- struct list_head list;
- struct omap_gem_object *omap_obj;
- enum omap_gem_op op;
- uint32_t read_target, write_target;
- /* notify called w/ sync_lock held */
- void (*notify)(void *arg);
- void *arg;
-};
-
-/* list of omap_gem_sync_waiter.. the notify fxn gets called back when
- * the read and/or write target count is achieved which can call a user
- * callback (ex. to kick 3d and/or 2d), wakeup blocked task (prep for
- * cpu access), etc.
- */
-static LIST_HEAD(waiters);
-
-static inline bool is_waiting(struct omap_gem_sync_waiter *waiter)
-{
- struct omap_gem_object *omap_obj = waiter->omap_obj;
- if ((waiter->op & OMAP_GEM_READ) &&
- (omap_obj->sync->read_complete < waiter->read_target))
- return true;
- if ((waiter->op & OMAP_GEM_WRITE) &&
- (omap_obj->sync->write_complete < waiter->write_target))
- return true;
- return false;
-}
-
-/* macro for sync debug.. */
-#define SYNCDBG 0
-#define SYNC(fmt, ...) do { if (SYNCDBG) \
- printk(KERN_ERR "%s:%d: "fmt"\n", \
- __func__, __LINE__, ##__VA_ARGS__); \
- } while (0)
-
-
-static void sync_op_update(void)
-{
- struct omap_gem_sync_waiter *waiter, *n;
- list_for_each_entry_safe(waiter, n, &waiters, list) {
- if (!is_waiting(waiter)) {
- list_del(&waiter->list);
- SYNC("notify: %p", waiter);
- waiter->notify(waiter->arg);
- kfree(waiter);
- }
- }
-}
-
-static inline int sync_op(struct drm_gem_object *obj,
- enum omap_gem_op op, bool start)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
-
- spin_lock(&sync_lock);
-
- if (!omap_obj->sync) {
- omap_obj->sync = kzalloc(sizeof(*omap_obj->sync), GFP_ATOMIC);
- if (!omap_obj->sync) {
- ret = -ENOMEM;
- goto unlock;
- }
- }
-
- if (start) {
- if (op & OMAP_GEM_READ)
- omap_obj->sync->read_pending++;
- if (op & OMAP_GEM_WRITE)
- omap_obj->sync->write_pending++;
- } else {
- if (op & OMAP_GEM_READ)
- omap_obj->sync->read_complete++;
- if (op & OMAP_GEM_WRITE)
- omap_obj->sync->write_complete++;
- sync_op_update();
- }
-
-unlock:
- spin_unlock(&sync_lock);
-
- return ret;
-}
-
-/* it is a bit lame to handle updates in this sort of polling way, but
- * in case of PVR, the GPU can directly update read/write complete
- * values, and not really tell us which ones it updated.. this also
- * means that sync_lock is not quite sufficient. So we'll need to
- * do something a bit better when it comes time to add support for
- * separate 2d hw..
- */
-void omap_gem_op_update(void)
-{
- spin_lock(&sync_lock);
- sync_op_update();
- spin_unlock(&sync_lock);
-}
-
-/* mark the start of read and/or write operation */
-int omap_gem_op_start(struct drm_gem_object *obj, enum omap_gem_op op)
-{
- return sync_op(obj, op, true);
-}
-
-int omap_gem_op_finish(struct drm_gem_object *obj, enum omap_gem_op op)
-{
- return sync_op(obj, op, false);
-}
-
-static DECLARE_WAIT_QUEUE_HEAD(sync_event);
-
-static void sync_notify(void *arg)
-{
- struct task_struct **waiter_task = arg;
- *waiter_task = NULL;
- wake_up_all(&sync_event);
-}
-
-int omap_gem_op_sync(struct drm_gem_object *obj, enum omap_gem_op op)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
- if (omap_obj->sync) {
- struct task_struct *waiter_task = current;
- struct omap_gem_sync_waiter *waiter =
- kzalloc(sizeof(*waiter), GFP_KERNEL);
-
- if (!waiter)
- return -ENOMEM;
-
- waiter->omap_obj = omap_obj;
- waiter->op = op;
- waiter->read_target = omap_obj->sync->read_pending;
- waiter->write_target = omap_obj->sync->write_pending;
- waiter->notify = sync_notify;
- waiter->arg = &waiter_task;
-
- spin_lock(&sync_lock);
- if (is_waiting(waiter)) {
- SYNC("waited: %p", waiter);
- list_add_tail(&waiter->list, &waiters);
- spin_unlock(&sync_lock);
- ret = wait_event_interruptible(sync_event,
- (waiter_task == NULL));
- spin_lock(&sync_lock);
- if (waiter_task) {
- SYNC("interrupted: %p", waiter);
- /* we were interrupted */
- list_del(&waiter->list);
- waiter_task = NULL;
- } else {
- /* freed in sync_op_update() */
- waiter = NULL;
- }
- }
- spin_unlock(&sync_lock);
-
- if (waiter)
- kfree(waiter);
- }
- return ret;
-}
-
-/* call fxn(arg), either synchronously or asynchronously if the op
- * is currently blocked.. fxn() can be called from any context
- *
- * (TODO for now fxn is called back from whichever context calls
- * omap_gem_op_update().. but this could be better defined later
- * if needed)
- *
- * TODO more code in common w/ _sync()..
- */
-int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op,
- void (*fxn)(void *arg), void *arg)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- if (omap_obj->sync) {
- struct omap_gem_sync_waiter *waiter =
- kzalloc(sizeof(*waiter), GFP_ATOMIC);
-
- if (!waiter)
- return -ENOMEM;
-
- waiter->omap_obj = omap_obj;
- waiter->op = op;
- waiter->read_target = omap_obj->sync->read_pending;
- waiter->write_target = omap_obj->sync->write_pending;
- waiter->notify = fxn;
- waiter->arg = arg;
-
- spin_lock(&sync_lock);
- if (is_waiting(waiter)) {
- SYNC("waited: %p", waiter);
- list_add_tail(&waiter->list, &waiters);
- spin_unlock(&sync_lock);
- return 0;
- }
-
- spin_unlock(&sync_lock);
- }
-
- /* no waiting.. */
- fxn(arg);
-
- return 0;
-}
-
-/* special API so PVR can update the buffer to use a sync-object allocated
- * from it's sync-obj heap. Only used for a newly allocated (from PVR's
- * perspective) sync-object, so we overwrite the new syncobj w/ values
- * from the already allocated syncobj (if there is one)
- */
-int omap_gem_set_sync_object(struct drm_gem_object *obj, void *syncobj)
-{
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
- int ret = 0;
-
- spin_lock(&sync_lock);
-
- if ((omap_obj->flags & OMAP_BO_EXT_SYNC) && !syncobj) {
- /* clearing a previously set syncobj */
- syncobj = kmemdup(omap_obj->sync, sizeof(*omap_obj->sync),
- GFP_ATOMIC);
- if (!syncobj) {
- ret = -ENOMEM;
- goto unlock;
- }
- omap_obj->flags &= ~OMAP_BO_EXT_SYNC;
- omap_obj->sync = syncobj;
- } else if (syncobj && !(omap_obj->flags & OMAP_BO_EXT_SYNC)) {
- /* replacing an existing syncobj */
- if (omap_obj->sync) {
- memcpy(syncobj, omap_obj->sync, sizeof(*omap_obj->sync));
- kfree(omap_obj->sync);
- }
- omap_obj->flags |= OMAP_BO_EXT_SYNC;
- omap_obj->sync = syncobj;
- }
-
-unlock:
- spin_unlock(&sync_lock);
- return ret;
-}
-
-int omap_gem_init_object(struct drm_gem_object *obj)
-{
- return -EINVAL; /* unused */
-}
-
-/* don't call directly.. called from GEM core when it is time to actually
- * free the object..
- */
-void omap_gem_free_object(struct drm_gem_object *obj)
-{
- struct drm_device *dev = obj->dev;
- struct omap_gem_object *omap_obj = to_omap_bo(obj);
-
- evict(obj);
-
- WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-
- list_del(&omap_obj->mm_list);
-
- if (obj->map_list.map)
- drm_gem_free_mmap_offset(obj);
-
- /* this means the object is still pinned.. which really should
- * not happen. I think..
- */
- WARN_ON(omap_obj->paddr_cnt > 0);
-
- /* don't free externally allocated backing memory */
- if (!(omap_obj->flags & OMAP_BO_EXT_MEM)) {
- if (omap_obj->pages)
- omap_gem_detach_pages(obj);
-
- if (!is_shmem(obj)) {
- dma_free_writecombine(dev->dev, obj->size,
- omap_obj->vaddr, omap_obj->paddr);
- } else if (omap_obj->vaddr) {
- vunmap(omap_obj->vaddr);
- }
- }
-
- /* don't free externally allocated syncobj */
- if (!(omap_obj->flags & OMAP_BO_EXT_SYNC))
- kfree(omap_obj->sync);
-
- drm_gem_object_release(obj);
-
- kfree(obj);
-}
-
-/* convenience method to construct a GEM buffer object, and userspace handle */
-int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
- union omap_gem_size gsize, uint32_t flags, uint32_t *handle)
-{
- struct drm_gem_object *obj;
- int ret;
-
- obj = omap_gem_new(dev, gsize, flags);
- if (!obj)
- return -ENOMEM;
-
- ret = drm_gem_handle_create(file, obj, handle);
- if (ret) {
- drm_gem_object_release(obj);
- kfree(obj); /* TODO isn't there a dtor to call? just copying i915 */
- return ret;
- }
-
- /* drop reference from allocate - handle holds it now */
- drm_gem_object_unreference_unlocked(obj);
-
- return 0;
-}
-
-/* GEM buffer object constructor */
-struct drm_gem_object *omap_gem_new(struct drm_device *dev,
- union omap_gem_size gsize, uint32_t flags)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_gem_object *omap_obj;
- struct drm_gem_object *obj = NULL;
- size_t size;
- int ret;
-
- if (flags & OMAP_BO_TILED) {
- if (!usergart) {
- dev_err(dev->dev, "Tiled buffers require DMM\n");
- goto fail;
- }
-
- /* tiled buffers are always shmem paged backed.. when they are
- * scanned out, they are remapped into DMM/TILER
- */
- flags &= ~OMAP_BO_SCANOUT;
-
- /* currently don't allow cached buffers.. there is some caching
- * stuff that needs to be handled better
- */
- flags &= ~(OMAP_BO_CACHED|OMAP_BO_UNCACHED);
- flags |= OMAP_BO_WC;
-
- /* align dimensions to slot boundaries... */
- tiler_align(gem2fmt(flags),
- &gsize.tiled.width, &gsize.tiled.height);
-
- /* ...and calculate size based on aligned dimensions */
- size = tiler_size(gem2fmt(flags),
- gsize.tiled.width, gsize.tiled.height);
- } else {
- size = PAGE_ALIGN(gsize.bytes);
- }
-
- omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL);
- if (!omap_obj)
- goto fail;
-
- list_add(&omap_obj->mm_list, &priv->obj_list);
-
- obj = &omap_obj->base;
-
- if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) {
- /* attempt to allocate contiguous memory if we don't
- * have DMM for remappign discontiguous buffers
- */
- omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size,
- &omap_obj->paddr, GFP_KERNEL);
- if (omap_obj->vaddr)
- flags |= OMAP_BO_DMA;
-
- }
-
- omap_obj->flags = flags;
-
- if (flags & OMAP_BO_TILED) {
- omap_obj->width = gsize.tiled.width;
- omap_obj->height = gsize.tiled.height;
- }
-
- if (flags & (OMAP_BO_DMA|OMAP_BO_EXT_MEM))
- ret = drm_gem_private_object_init(dev, obj, size);
- else
- ret = drm_gem_object_init(dev, obj, size);
-
- if (ret)
- goto fail;
-
- return obj;
-
-fail:
- if (obj)
- omap_gem_free_object(obj);
-
- return NULL;
-}
-
-/* init/cleanup.. if DMM is used, we need to set some stuff up.. */
-void omap_gem_init(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- const enum tiler_fmt fmts[] = {
- TILFMT_8BIT, TILFMT_16BIT, TILFMT_32BIT
- };
- int i, j;
-
- if (!dmm_is_available()) {
- /* DMM only supported on OMAP4 and later, so this isn't fatal */
- dev_warn(dev->dev, "DMM not available, disable DMM support\n");
- return;
- }
-
- usergart = kcalloc(3, sizeof(*usergart), GFP_KERNEL);
- if (!usergart)
- return;
-
- /* reserve 4k aligned/wide regions for userspace mappings: */
- for (i = 0; i < ARRAY_SIZE(fmts); i++) {
- uint16_t h = 1, w = PAGE_SIZE >> i;
- tiler_align(fmts[i], &w, &h);
- /* note: since each region is 1 4kb page wide, and minimum
- * number of rows, the height ends up being the same as the
- * # of pages in the region
- */
- usergart[i].height = h;
- usergart[i].height_shift = ilog2(h);
- usergart[i].stride_pfn = tiler_stride(fmts[i], 0) >> PAGE_SHIFT;
- usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i);
- for (j = 0; j < NUM_USERGART_ENTRIES; j++) {
- struct usergart_entry *entry = &usergart[i].entry[j];
- struct tiler_block *block =
- tiler_reserve_2d(fmts[i], w, h,
- PAGE_SIZE);
- if (IS_ERR(block)) {
- dev_err(dev->dev,
- "reserve failed: %d, %d, %ld\n",
- i, j, PTR_ERR(block));
- return;
- }
- entry->paddr = tiler_ssptr(block);
- entry->block = block;
-
- DBG("%d:%d: %dx%d: paddr=%08x stride=%d", i, j, w, h,
- entry->paddr,
- usergart[i].stride_pfn << PAGE_SHIFT);
- }
- }
-
- priv->has_dmm = true;
-}
-
-void omap_gem_deinit(struct drm_device *dev)
-{
- /* I believe we can rely on there being no more outstanding GEM
- * objects which could depend on usergart/dmm at this point.
- */
- kfree(usergart);
-}
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c
deleted file mode 100644
index a3236abfca3..00000000000
--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_gem_dmabuf.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-#include <linux/dma-buf.h>
-
-static struct sg_table *omap_gem_map_dma_buf(
- struct dma_buf_attachment *attachment,
- enum dma_data_direction dir)
-{
- struct drm_gem_object *obj = attachment->dmabuf->priv;
- struct sg_table *sg;
- dma_addr_t paddr;
- int ret;
-
- sg = kzalloc(sizeof(*sg), GFP_KERNEL);
- if (!sg)
- return ERR_PTR(-ENOMEM);
-
- /* camera, etc, need physically contiguous.. but we need a
- * better way to know this..
- */
- ret = omap_gem_get_paddr(obj, &paddr, true);
- if (ret)
- goto out;
-
- ret = sg_alloc_table(sg, 1, GFP_KERNEL);
- if (ret)
- goto out;
-
- sg_init_table(sg->sgl, 1);
- sg_dma_len(sg->sgl) = obj->size;
- sg_set_page(sg->sgl, pfn_to_page(PFN_DOWN(paddr)), obj->size, 0);
- sg_dma_address(sg->sgl) = paddr;
-
- /* this should be after _get_paddr() to ensure we have pages attached */
- omap_gem_dma_sync(obj, dir);
-
- return sg;
-out:
- kfree(sg);
- return ERR_PTR(ret);
-}
-
-static void omap_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
- struct sg_table *sg, enum dma_data_direction dir)
-{
- struct drm_gem_object *obj = attachment->dmabuf->priv;
- omap_gem_put_paddr(obj);
- sg_free_table(sg);
- kfree(sg);
-}
-
-static void omap_gem_dmabuf_release(struct dma_buf *buffer)
-{
- struct drm_gem_object *obj = buffer->priv;
- /* release reference that was taken when dmabuf was exported
- * in omap_gem_prime_set()..
- */
- drm_gem_object_unreference_unlocked(obj);
-}
-
-
-static int omap_gem_dmabuf_begin_cpu_access(struct dma_buf *buffer,
- size_t start, size_t len, enum dma_data_direction dir)
-{
- struct drm_gem_object *obj = buffer->priv;
- struct page **pages;
- if (omap_gem_flags(obj) & OMAP_BO_TILED) {
- /* TODO we would need to pin at least part of the buffer to
- * get de-tiled view. For now just reject it.
- */
- return -ENOMEM;
- }
- /* make sure we have the pages: */
- return omap_gem_get_pages(obj, &pages, true);
-}
-
-static void omap_gem_dmabuf_end_cpu_access(struct dma_buf *buffer,
- size_t start, size_t len, enum dma_data_direction dir)
-{
- struct drm_gem_object *obj = buffer->priv;
- omap_gem_put_pages(obj);
-}
-
-
-static void *omap_gem_dmabuf_kmap_atomic(struct dma_buf *buffer,
- unsigned long page_num)
-{
- struct drm_gem_object *obj = buffer->priv;
- struct page **pages;
- omap_gem_get_pages(obj, &pages, false);
- omap_gem_cpu_sync(obj, page_num);
- return kmap_atomic(pages[page_num]);
-}
-
-static void omap_gem_dmabuf_kunmap_atomic(struct dma_buf *buffer,
- unsigned long page_num, void *addr)
-{
- kunmap_atomic(addr);
-}
-
-static void *omap_gem_dmabuf_kmap(struct dma_buf *buffer,
- unsigned long page_num)
-{
- struct drm_gem_object *obj = buffer->priv;
- struct page **pages;
- omap_gem_get_pages(obj, &pages, false);
- omap_gem_cpu_sync(obj, page_num);
- return kmap(pages[page_num]);
-}
-
-static void omap_gem_dmabuf_kunmap(struct dma_buf *buffer,
- unsigned long page_num, void *addr)
-{
- struct drm_gem_object *obj = buffer->priv;
- struct page **pages;
- omap_gem_get_pages(obj, &pages, false);
- kunmap(pages[page_num]);
-}
-
-/*
- * TODO maybe we can split up drm_gem_mmap to avoid duplicating
- * some here.. or at least have a drm_dmabuf_mmap helper.
- */
-static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
- struct vm_area_struct *vma)
-{
- struct drm_gem_object *obj = buffer->priv;
- int ret = 0;
-
- if (WARN_ON(!obj->filp))
- return -EINVAL;
-
- /* Check for valid size. */
- if (omap_gem_mmap_size(obj) < vma->vm_end - vma->vm_start) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- if (!obj->dev->driver->gem_vm_ops) {
- ret = -EINVAL;
- goto out_unlock;
- }
-
- vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_ops = obj->dev->driver->gem_vm_ops;
- vma->vm_private_data = obj;
- vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
-
- /* Take a ref for this mapping of the object, so that the fault
- * handler can dereference the mmap offset's pointer to the object.
- * This reference is cleaned up by the corresponding vm_close
- * (which should happen whether the vma was created by this call, or
- * by a vm_open due to mremap or partial unmap or whatever).
- */
- vma->vm_ops->open(vma);
-
-out_unlock:
-
- return omap_gem_mmap_obj(obj, vma);
-}
-
-struct dma_buf_ops omap_dmabuf_ops = {
- .map_dma_buf = omap_gem_map_dma_buf,
- .unmap_dma_buf = omap_gem_unmap_dma_buf,
- .release = omap_gem_dmabuf_release,
- .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access,
- .end_cpu_access = omap_gem_dmabuf_end_cpu_access,
- .kmap_atomic = omap_gem_dmabuf_kmap_atomic,
- .kunmap_atomic = omap_gem_dmabuf_kunmap_atomic,
- .kmap = omap_gem_dmabuf_kmap,
- .kunmap = omap_gem_dmabuf_kunmap,
- .mmap = omap_gem_dmabuf_mmap,
-};
-
-struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
- struct drm_gem_object *obj, int flags)
-{
- return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
-}
-
-struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
- struct dma_buf *buffer)
-{
- struct drm_gem_object *obj;
-
- /* is this one of own objects? */
- if (buffer->ops == &omap_dmabuf_ops) {
- obj = buffer->priv;
- /* is it from our device? */
- if (obj->dev == dev) {
- /*
- * Importing dmabuf exported from out own gem increases
- * refcount on gem itself instead of f_count of dmabuf.
- */
- drm_gem_object_reference(obj);
- dma_buf_put(buffer);
- return obj;
- }
- }
-
- /*
- * TODO add support for importing buffers from other devices..
- * for now we don't need this but would be nice to add eventually
- */
- return ERR_PTR(-EINVAL);
-}
diff --git a/drivers/staging/omapdrm/omap_gem_helpers.c b/drivers/staging/omapdrm/omap_gem_helpers.c
deleted file mode 100644
index ffb8cceaeb4..00000000000
--- a/drivers/staging/omapdrm/omap_gem_helpers.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_gem_helpers.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* temporary copy of drm_gem_{get,put}_pages() until the
- * "drm/gem: add functions to get/put pages" patch is merged..
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/shmem_fs.h>
-
-#include <drm/drmP.h>
-
-/**
- * drm_gem_get_pages - helper to allocate backing pages for a GEM object
- * @obj: obj in question
- * @gfpmask: gfp mask of requested pages
- */
-struct page **_drm_gem_get_pages(struct drm_gem_object *obj, gfp_t gfpmask)
-{
- struct inode *inode;
- struct address_space *mapping;
- struct page *p, **pages;
- int i, npages;
-
- /* This is the shared memory object that backs the GEM resource */
- inode = obj->filp->f_path.dentry->d_inode;
- mapping = inode->i_mapping;
-
- npages = obj->size >> PAGE_SHIFT;
-
- pages = drm_malloc_ab(npages, sizeof(struct page *));
- if (pages == NULL)
- return ERR_PTR(-ENOMEM);
-
- gfpmask |= mapping_gfp_mask(mapping);
-
- for (i = 0; i < npages; i++) {
- p = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
- if (IS_ERR(p))
- goto fail;
- pages[i] = p;
-
- /* There is a hypothetical issue w/ drivers that require
- * buffer memory in the low 4GB.. if the pages are un-
- * pinned, and swapped out, they can end up swapped back
- * in above 4GB. If pages are already in memory, then
- * shmem_read_mapping_page_gfp will ignore the gfpmask,
- * even if the already in-memory page disobeys the mask.
- *
- * It is only a theoretical issue today, because none of
- * the devices with this limitation can be populated with
- * enough memory to trigger the issue. But this BUG_ON()
- * is here as a reminder in case the problem with
- * shmem_read_mapping_page_gfp() isn't solved by the time
- * it does become a real issue.
- *
- * See this thread: http://lkml.org/lkml/2011/7/11/238
- */
- BUG_ON((gfpmask & __GFP_DMA32) &&
- (page_to_pfn(p) >= 0x00100000UL));
- }
-
- return pages;
-
-fail:
- while (i--)
- page_cache_release(pages[i]);
-
- drm_free_large(pages);
- return ERR_CAST(p);
-}
-
-/**
- * drm_gem_put_pages - helper to free backing pages for a GEM object
- * @obj: obj in question
- * @pages: pages to free
- */
-void _drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
- bool dirty, bool accessed)
-{
- int i, npages;
-
- npages = obj->size >> PAGE_SHIFT;
-
- for (i = 0; i < npages; i++) {
- if (dirty)
- set_page_dirty(pages[i]);
-
- if (accessed)
- mark_page_accessed(pages[i]);
-
- /* Undo the reference we took when populating the table */
- page_cache_release(pages[i]);
- }
-
- drm_free_large(pages);
-}
-
-int
-_drm_gem_create_mmap_offset_size(struct drm_gem_object *obj, size_t size)
-{
- struct drm_device *dev = obj->dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_map_list *list;
- struct drm_local_map *map;
- int ret = 0;
-
- /* Set the object up for mmap'ing */
- list = &obj->map_list;
- list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
- if (!list->map)
- return -ENOMEM;
-
- map = list->map;
- map->type = _DRM_GEM;
- map->size = size;
- map->handle = obj;
-
- /* Get a DRM GEM mmap offset allocated... */
- list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
- size / PAGE_SIZE, 0, 0);
-
- if (!list->file_offset_node) {
- DRM_ERROR("failed to allocate offset for bo %d\n", obj->name);
- ret = -ENOSPC;
- goto out_free_list;
- }
-
- list->file_offset_node = drm_mm_get_block(list->file_offset_node,
- size / PAGE_SIZE, 0);
- if (!list->file_offset_node) {
- ret = -ENOMEM;
- goto out_free_list;
- }
-
- list->hash.key = list->file_offset_node->start;
- ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
- if (ret) {
- DRM_ERROR("failed to add to map hash\n");
- goto out_free_mm;
- }
-
- return 0;
-
-out_free_mm:
- drm_mm_put_block(list->file_offset_node);
-out_free_list:
- kfree(list->map);
- list->map = NULL;
-
- return ret;
-}
diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c
deleted file mode 100644
index 2629ba7be6c..00000000000
--- a/drivers/staging/omapdrm/omap_irq.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_irq.c
- *
- * Copyright (C) 2012 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "omap_drv.h"
-
-static DEFINE_SPINLOCK(list_lock);
-
-static void omap_irq_error_handler(struct omap_drm_irq *irq,
- uint32_t irqstatus)
-{
- DRM_ERROR("errors: %08x\n", irqstatus);
-}
-
-/* call with list_lock and dispc runtime held */
-static void omap_irq_update(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_drm_irq *irq;
- uint32_t irqmask = priv->vblank_mask;
-
- BUG_ON(!spin_is_locked(&list_lock));
-
- list_for_each_entry(irq, &priv->irq_list, node)
- irqmask |= irq->irqmask;
-
- DBG("irqmask=%08x", irqmask);
-
- dispc_write_irqenable(irqmask);
- dispc_read_irqenable(); /* flush posted write */
-}
-
-void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
-{
- struct omap_drm_private *priv = dev->dev_private;
- unsigned long flags;
-
- dispc_runtime_get();
- spin_lock_irqsave(&list_lock, flags);
-
- if (!WARN_ON(irq->registered)) {
- irq->registered = true;
- list_add(&irq->node, &priv->irq_list);
- omap_irq_update(dev);
- }
-
- spin_unlock_irqrestore(&list_lock, flags);
- dispc_runtime_put();
-}
-
-void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
-{
- unsigned long flags;
-
- dispc_runtime_get();
- spin_lock_irqsave(&list_lock, flags);
-
- if (!WARN_ON(!irq->registered)) {
- irq->registered = false;
- list_del(&irq->node);
- omap_irq_update(dev);
- }
-
- spin_unlock_irqrestore(&list_lock, flags);
- dispc_runtime_put();
-}
-
-struct omap_irq_wait {
- struct omap_drm_irq irq;
- int count;
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(wait_event);
-
-static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
- struct omap_irq_wait *wait =
- container_of(irq, struct omap_irq_wait, irq);
- wait->count--;
- wake_up_all(&wait_event);
-}
-
-struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
- uint32_t irqmask, int count)
-{
- struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
- wait->irq.irq = wait_irq;
- wait->irq.irqmask = irqmask;
- wait->count = count;
- omap_irq_register(dev, &wait->irq);
- return wait;
-}
-
-int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
- unsigned long timeout)
-{
- int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
- omap_irq_unregister(dev, &wait->irq);
- kfree(wait);
- if (ret == 0)
- return -1;
- return 0;
-}
-
-/**
- * enable_vblank - enable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Enable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- *
- * RETURNS
- * Zero on success, appropriate errno if the given @crtc's vblank
- * interrupt cannot be enabled.
- */
-int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
-{
- struct omap_drm_private *priv = dev->dev_private;
- unsigned long flags;
-
- DBG("dev=%p, crtc=%d", dev, crtc);
-
- dispc_runtime_get();
- spin_lock_irqsave(&list_lock, flags);
- priv->vblank_mask |= pipe2vbl(crtc);
- omap_irq_update(dev);
- spin_unlock_irqrestore(&list_lock, flags);
- dispc_runtime_put();
-
- return 0;
-}
-
-/**
- * disable_vblank - disable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Disable vblank interrupts for @crtc. If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- */
-void omap_irq_disable_vblank(struct drm_device *dev, int crtc)
-{
- struct omap_drm_private *priv = dev->dev_private;
- unsigned long flags;
-
- DBG("dev=%p, crtc=%d", dev, crtc);
-
- dispc_runtime_get();
- spin_lock_irqsave(&list_lock, flags);
- priv->vblank_mask &= ~pipe2vbl(crtc);
- omap_irq_update(dev);
- spin_unlock_irqrestore(&list_lock, flags);
- dispc_runtime_put();
-}
-
-irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
-{
- struct drm_device *dev = (struct drm_device *) arg;
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_drm_irq *handler, *n;
- unsigned long flags;
- unsigned int id;
- u32 irqstatus;
-
- irqstatus = dispc_read_irqstatus();
- dispc_clear_irqstatus(irqstatus);
- dispc_read_irqstatus(); /* flush posted write */
-
- VERB("irqs: %08x", irqstatus);
-
- for (id = 0; id < priv->num_crtcs; id++)
- if (irqstatus & pipe2vbl(id))
- drm_handle_vblank(dev, id);
-
- spin_lock_irqsave(&list_lock, flags);
- list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
- if (handler->irqmask & irqstatus) {
- spin_unlock_irqrestore(&list_lock, flags);
- handler->irq(handler, handler->irqmask & irqstatus);
- spin_lock_irqsave(&list_lock, flags);
- }
- }
- spin_unlock_irqrestore(&list_lock, flags);
-
- return IRQ_HANDLED;
-}
-
-void omap_irq_preinstall(struct drm_device *dev)
-{
- DBG("dev=%p", dev);
- dispc_runtime_get();
- dispc_clear_irqstatus(0xffffffff);
- dispc_runtime_put();
-}
-
-int omap_irq_postinstall(struct drm_device *dev)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct omap_drm_irq *error_handler = &priv->error_handler;
-
- DBG("dev=%p", dev);
-
- INIT_LIST_HEAD(&priv->irq_list);
-
- error_handler->irq = omap_irq_error_handler;
- error_handler->irqmask = DISPC_IRQ_OCP_ERR;
-
- /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
- * we just need to ignore it while enabling tv-out
- */
- error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
-
- omap_irq_register(dev, error_handler);
-
- return 0;
-}
-
-void omap_irq_uninstall(struct drm_device *dev)
-{
- DBG("dev=%p", dev);
- // TODO prolly need to call drm_irq_uninstall() somewhere too
-}
-
-/*
- * We need a special version, instead of just using drm_irq_install(),
- * because we need to register the irq via omapdss. Once omapdss and
- * omapdrm are merged together we can assign the dispc hwmod data to
- * ourselves and drop these and just use drm_irq_{install,uninstall}()
- */
-
-int omap_drm_irq_install(struct drm_device *dev)
-{
- int ret;
-
- mutex_lock(&dev->struct_mutex);
-
- if (dev->irq_enabled) {
- mutex_unlock(&dev->struct_mutex);
- return -EBUSY;
- }
- dev->irq_enabled = 1;
- mutex_unlock(&dev->struct_mutex);
-
- /* Before installing handler */
- if (dev->driver->irq_preinstall)
- dev->driver->irq_preinstall(dev);
-
- ret = dispc_request_irq(dev->driver->irq_handler, dev);
-
- if (ret < 0) {
- mutex_lock(&dev->struct_mutex);
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
-
- /* After installing handler */
- if (dev->driver->irq_postinstall)
- ret = dev->driver->irq_postinstall(dev);
-
- if (ret < 0) {
- mutex_lock(&dev->struct_mutex);
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
- dispc_free_irq(dev);
- }
-
- return ret;
-}
-
-int omap_drm_irq_uninstall(struct drm_device *dev)
-{
- unsigned long irqflags;
- int irq_enabled, i;
-
- mutex_lock(&dev->struct_mutex);
- irq_enabled = dev->irq_enabled;
- dev->irq_enabled = 0;
- mutex_unlock(&dev->struct_mutex);
-
- /*
- * Wake up any waiters so they don't hang.
- */
- if (dev->num_crtcs) {
- spin_lock_irqsave(&dev->vbl_lock, irqflags);
- for (i = 0; i < dev->num_crtcs; i++) {
- DRM_WAKEUP(&dev->vbl_queue[i]);
- dev->vblank_enabled[i] = 0;
- dev->last_vblank[i] =
- dev->driver->get_vblank_counter(dev, i);
- }
- spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
- }
-
- if (!irq_enabled)
- return -EINVAL;
-
- if (dev->driver->irq_uninstall)
- dev->driver->irq_uninstall(dev);
-
- dispc_free_irq(dev);
-
- return 0;
-}
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
deleted file mode 100644
index c063476db3b..00000000000
--- a/drivers/staging/omapdrm/omap_plane.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * drivers/staging/omapdrm/omap_plane.c
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob.clark@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/kfifo.h>
-
-#include "omap_drv.h"
-#include "omap_dmm_tiler.h"
-
-/* some hackery because omapdss has an 'enum omap_plane' (which would be
- * better named omap_plane_id).. and compiler seems unhappy about having
- * both a 'struct omap_plane' and 'enum omap_plane'
- */
-#define omap_plane _omap_plane
-
-/*
- * plane funcs
- */
-
-struct callback {
- void (*fxn)(void *);
- void *arg;
-};
-
-#define to_omap_plane(x) container_of(x, struct omap_plane, base)
-
-struct omap_plane {
- struct drm_plane base;
- int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */
- const char *name;
- struct omap_overlay_info info;
- struct omap_drm_apply apply;
-
- /* position/orientation of scanout within the fb: */
- struct omap_drm_window win;
- bool enabled;
-
- /* last fb that we pinned: */
- struct drm_framebuffer *pinned_fb;
-
- uint32_t nformats;
- uint32_t formats[32];
-
- struct omap_drm_irq error_irq;
-
- /* set of bo's pending unpin until next post_apply() */
- DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *);
-
- // XXX maybe get rid of this and handle vblank in crtc too?
- struct callback apply_done_cb;
-};
-
-static void unpin(void *arg, struct drm_gem_object *bo)
-{
- struct drm_plane *plane = arg;
- struct omap_plane *omap_plane = to_omap_plane(plane);
-
- if (kfifo_put(&omap_plane->unpin_fifo,
- (const struct drm_gem_object **)&bo)) {
- /* also hold a ref so it isn't free'd while pinned */
- drm_gem_object_reference(bo);
- } else {
- dev_err(plane->dev->dev, "unpin fifo full!\n");
- omap_gem_put_paddr(bo);
- }
-}
-
-/* update which fb (if any) is pinned for scanout */
-static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- struct drm_framebuffer *pinned_fb = omap_plane->pinned_fb;
-
- if (pinned_fb != fb) {
- int ret;
-
- DBG("%p -> %p", pinned_fb, fb);
-
- if (fb)
- drm_framebuffer_reference(fb);
-
- ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin);
-
- if (pinned_fb)
- drm_framebuffer_unreference(pinned_fb);
-
- if (ret) {
- dev_err(plane->dev->dev, "could not swap %p -> %p\n",
- omap_plane->pinned_fb, fb);
- if (fb)
- drm_framebuffer_unreference(fb);
- omap_plane->pinned_fb = NULL;
- return ret;
- }
-
- omap_plane->pinned_fb = fb;
- }
-
- return 0;
-}
-
-static void omap_plane_pre_apply(struct omap_drm_apply *apply)
-{
- struct omap_plane *omap_plane =
- container_of(apply, struct omap_plane, apply);
- struct omap_drm_window *win = &omap_plane->win;
- struct drm_plane *plane = &omap_plane->base;
- struct drm_device *dev = plane->dev;
- struct omap_overlay_info *info = &omap_plane->info;
- struct drm_crtc *crtc = plane->crtc;
- enum omap_channel channel;
- bool enabled = omap_plane->enabled && crtc;
- bool ilace, replication;
- int ret;
-
- DBG("%s, enabled=%d", omap_plane->name, enabled);
-
- /* if fb has changed, pin new fb: */
- update_pin(plane, enabled ? plane->fb : NULL);
-
- if (!enabled) {
- dispc_ovl_enable(omap_plane->id, false);
- return;
- }
-
- channel = omap_crtc_channel(crtc);
-
- /* update scanout: */
- omap_framebuffer_update_scanout(plane->fb, win, info);
-
- DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
- info->out_width, info->out_height,
- info->screen_width);
- DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
- info->paddr, info->p_uv_addr);
-
- /* TODO: */
- ilace = false;
- replication = false;
-
- /* and finally, update omapdss: */
- ret = dispc_ovl_setup(omap_plane->id, info,
- replication, omap_crtc_timings(crtc), false);
- if (ret) {
- dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
- return;
- }
-
- dispc_ovl_enable(omap_plane->id, true);
- dispc_ovl_set_channel_out(omap_plane->id, channel);
-}
-
-static void omap_plane_post_apply(struct omap_drm_apply *apply)
-{
- struct omap_plane *omap_plane =
- container_of(apply, struct omap_plane, apply);
- struct drm_plane *plane = &omap_plane->base;
- struct omap_overlay_info *info = &omap_plane->info;
- struct drm_gem_object *bo = NULL;
- struct callback cb;
-
- cb = omap_plane->apply_done_cb;
- omap_plane->apply_done_cb.fxn = NULL;
-
- while (kfifo_get(&omap_plane->unpin_fifo, &bo)) {
- omap_gem_put_paddr(bo);
- drm_gem_object_unreference_unlocked(bo);
- }
-
- if (cb.fxn)
- cb.fxn(cb.arg);
-
- if (omap_plane->enabled) {
- omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
- info->out_width, info->out_height);
- }
-}
-
-static int apply(struct drm_plane *plane)
-{
- if (plane->crtc) {
- struct omap_plane *omap_plane = to_omap_plane(plane);
- return omap_crtc_apply(plane->crtc, &omap_plane->apply);
- }
- return 0;
-}
-
-int omap_plane_mode_set(struct drm_plane *plane,
- struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h,
- void (*fxn)(void *), void *arg)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- struct omap_drm_window *win = &omap_plane->win;
-
- win->crtc_x = crtc_x;
- win->crtc_y = crtc_y;
- win->crtc_w = crtc_w;
- win->crtc_h = crtc_h;
-
- /* src values are in Q16 fixed point, convert to integer: */
- win->src_x = src_x >> 16;
- win->src_y = src_y >> 16;
- win->src_w = src_w >> 16;
- win->src_h = src_h >> 16;
-
- if (fxn) {
- /* omap_crtc should ensure that a new page flip
- * isn't permitted while there is one pending:
- */
- BUG_ON(omap_plane->apply_done_cb.fxn);
-
- omap_plane->apply_done_cb.fxn = fxn;
- omap_plane->apply_done_cb.arg = arg;
- }
-
- plane->fb = fb;
- plane->crtc = crtc;
-
- return apply(plane);
-}
-
-static int omap_plane_update(struct drm_plane *plane,
- struct drm_crtc *crtc, struct drm_framebuffer *fb,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h,
- uint32_t src_x, uint32_t src_y,
- uint32_t src_w, uint32_t src_h)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- omap_plane->enabled = true;
- return omap_plane_mode_set(plane, crtc, fb,
- crtc_x, crtc_y, crtc_w, crtc_h,
- src_x, src_y, src_w, src_h,
- NULL, NULL);
-}
-
-static int omap_plane_disable(struct drm_plane *plane)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- omap_plane->win.rotation = BIT(DRM_ROTATE_0);
- return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
-}
-
-static void omap_plane_destroy(struct drm_plane *plane)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
-
- DBG("%s", omap_plane->name);
-
- omap_irq_unregister(plane->dev, &omap_plane->error_irq);
-
- omap_plane_disable(plane);
- drm_plane_cleanup(plane);
-
- WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo));
- kfifo_free(&omap_plane->unpin_fifo);
-
- kfree(omap_plane);
-}
-
-int omap_plane_dpms(struct drm_plane *plane, int mode)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- bool enabled = (mode == DRM_MODE_DPMS_ON);
- int ret = 0;
-
- if (enabled != omap_plane->enabled) {
- omap_plane->enabled = enabled;
- ret = apply(plane);
- }
-
- return ret;
-}
-
-/* helper to install properties which are common to planes and crtcs */
-void omap_plane_install_properties(struct drm_plane *plane,
- struct drm_mode_object *obj)
-{
- struct drm_device *dev = plane->dev;
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_property *prop;
-
- if (priv->has_dmm) {
- prop = priv->rotation_prop;
- if (!prop) {
- const struct drm_prop_enum_list props[] = {
- { DRM_ROTATE_0, "rotate-0" },
- { DRM_ROTATE_90, "rotate-90" },
- { DRM_ROTATE_180, "rotate-180" },
- { DRM_ROTATE_270, "rotate-270" },
- { DRM_REFLECT_X, "reflect-x" },
- { DRM_REFLECT_Y, "reflect-y" },
- };
- prop = drm_property_create_bitmask(dev, 0, "rotation",
- props, ARRAY_SIZE(props));
- if (prop == NULL)
- return;
- priv->rotation_prop = prop;
- }
- drm_object_attach_property(obj, prop, 0);
- }
-
- prop = priv->zorder_prop;
- if (!prop) {
- prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
- if (prop == NULL)
- return;
- priv->zorder_prop = prop;
- }
- drm_object_attach_property(obj, prop, 0);
-}
-
-int omap_plane_set_property(struct drm_plane *plane,
- struct drm_property *property, uint64_t val)
-{
- struct omap_plane *omap_plane = to_omap_plane(plane);
- struct omap_drm_private *priv = plane->dev->dev_private;
- int ret = -EINVAL;
-
- if (property == priv->rotation_prop) {
- DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
- omap_plane->win.rotation = val;
- ret = apply(plane);
- } else if (property == priv->zorder_prop) {
- DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
- omap_plane->info.zorder = val;
- ret = apply(plane);
- }
-
- return ret;
-}
-
-static const struct drm_plane_funcs omap_plane_funcs = {
- .update_plane = omap_plane_update,
- .disable_plane = omap_plane_disable,
- .destroy = omap_plane_destroy,
- .set_property = omap_plane_set_property,
-};
-
-static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
-{
- struct omap_plane *omap_plane =
- container_of(irq, struct omap_plane, error_irq);
- DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus);
-}
-
-static const char *plane_names[] = {
- [OMAP_DSS_GFX] = "gfx",
- [OMAP_DSS_VIDEO1] = "vid1",
- [OMAP_DSS_VIDEO2] = "vid2",
- [OMAP_DSS_VIDEO3] = "vid3",
-};
-
-static const uint32_t error_irqs[] = {
- [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
- [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
- [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
- [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
-};
-
-/* initialize plane */
-struct drm_plane *omap_plane_init(struct drm_device *dev,
- int id, bool private_plane)
-{
- struct omap_drm_private *priv = dev->dev_private;
- struct drm_plane *plane = NULL;
- struct omap_plane *omap_plane;
- struct omap_overlay_info *info;
- int ret;
-
- DBG("%s: priv=%d", plane_names[id], private_plane);
-
- omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
- if (!omap_plane)
- goto fail;
-
- ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
- if (ret) {
- dev_err(dev->dev, "could not allocate unpin FIFO\n");
- goto fail;
- }
-
- omap_plane->nformats = omap_framebuffer_get_formats(
- omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
- dss_feat_get_supported_color_modes(id));
- omap_plane->id = id;
- omap_plane->name = plane_names[id];
-
- plane = &omap_plane->base;
-
- omap_plane->apply.pre_apply = omap_plane_pre_apply;
- omap_plane->apply.post_apply = omap_plane_post_apply;
-
- omap_plane->error_irq.irqmask = error_irqs[id];
- omap_plane->error_irq.irq = omap_plane_error_irq;
- omap_irq_register(dev, &omap_plane->error_irq);
-
- drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs,
- omap_plane->formats, omap_plane->nformats, private_plane);
-
- omap_plane_install_properties(plane, &plane->base);
-
- /* get our starting configuration, set defaults for parameters
- * we don't currently use, etc:
- */
- info = &omap_plane->info;
- info->rotation_type = OMAP_DSS_ROT_DMA;
- info->rotation = OMAP_DSS_ROT_0;
- info->global_alpha = 0xff;
- info->mirror = 0;
-
- /* Set defaults depending on whether we are a CRTC or overlay
- * layer.
- * TODO add ioctl to give userspace an API to change this.. this
- * will come in a subsequent patch.
- */
- if (private_plane)
- omap_plane->info.zorder = 0;
- else
- omap_plane->info.zorder = id;
-
- return plane;
-
-fail:
- if (plane)
- omap_plane_destroy(plane);
-
- return NULL;
-}
diff --git a/drivers/staging/omapdrm/tcm-sita.c b/drivers/staging/omapdrm/tcm-sita.c
deleted file mode 100644
index efb60951054..00000000000
--- a/drivers/staging/omapdrm/tcm-sita.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
- * tcm-sita.c
- *
- * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
- *
- * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
- * Lajos Molnar <molnar@ti.com>
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * This package is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-
-#include "tcm-sita.h"
-
-#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
-
-/* Individual selection criteria for different scan areas */
-static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
-static s32 CR_R2L_T2B = CR_DIAGONAL_BALANCE;
-
-/*********************************************
- * TCM API - Sita Implementation
- *********************************************/
-static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
- struct tcm_area *area);
-static s32 sita_reserve_1d(struct tcm *tcm, u32 slots, struct tcm_area *area);
-static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
-static void sita_deinit(struct tcm *tcm);
-
-/*********************************************
- * Main Scanner functions
- *********************************************/
-static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *area);
-
-static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *field, struct tcm_area *area);
-
-static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *field, struct tcm_area *area);
-
-static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
- struct tcm_area *field, struct tcm_area *area);
-
-/*********************************************
- * Support Infrastructure Methods
- *********************************************/
-static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
-
-static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
- struct tcm_area *field, s32 criteria,
- struct score *best);
-
-static void get_nearness_factor(struct tcm_area *field,
- struct tcm_area *candidate,
- struct nearness_factor *nf);
-
-static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
- struct neighbor_stats *stat);
-
-static void fill_area(struct tcm *tcm,
- struct tcm_area *area, struct tcm_area *parent);
-
-
-/*********************************************/
-
-/*********************************************
- * Utility Methods
- *********************************************/
-struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr)
-{
- struct tcm *tcm;
- struct sita_pvt *pvt;
- struct tcm_area area = {0};
- s32 i;
-
- if (width == 0 || height == 0)
- return NULL;
-
- tcm = kmalloc(sizeof(*tcm), GFP_KERNEL);
- pvt = kmalloc(sizeof(*pvt), GFP_KERNEL);
- if (!tcm || !pvt)
- goto error;
-
- memset(tcm, 0, sizeof(*tcm));
- memset(pvt, 0, sizeof(*pvt));
-
- /* Updating the pointers to SiTA implementation APIs */
- tcm->height = height;
- tcm->width = width;
- tcm->reserve_2d = sita_reserve_2d;
- tcm->reserve_1d = sita_reserve_1d;
- tcm->free = sita_free;
- tcm->deinit = sita_deinit;
- tcm->pvt = (void *)pvt;
-
- spin_lock_init(&(pvt->lock));
-
- /* Creating tam map */
- pvt->map = kmalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
- if (!pvt->map)
- goto error;
-
- for (i = 0; i < tcm->width; i++) {
- pvt->map[i] =
- kmalloc(sizeof(**pvt->map) * tcm->height,
- GFP_KERNEL);
- if (pvt->map[i] == NULL) {
- while (i--)
- kfree(pvt->map[i]);
- kfree(pvt->map);
- goto error;
- }
- }
-
- if (attr && attr->x <= tcm->width && attr->y <= tcm->height) {
- pvt->div_pt.x = attr->x;
- pvt->div_pt.y = attr->y;
-
- } else {
- /* Defaulting to 3:1 ratio on width for 2D area split */
- /* Defaulting to 3:1 ratio on height for 2D and 1D split */
- pvt->div_pt.x = (tcm->width * 3) / 4;
- pvt->div_pt.y = (tcm->height * 3) / 4;
- }
-
- spin_lock(&(pvt->lock));
- assign(&area, 0, 0, width - 1, height - 1);
- fill_area(tcm, &area, NULL);
- spin_unlock(&(pvt->lock));
- return tcm;
-
-error:
- kfree(tcm);
- kfree(pvt);
- return NULL;
-}
-
-static void sita_deinit(struct tcm *tcm)
-{
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
- struct tcm_area area = {0};
- s32 i;
-
- area.p1.x = tcm->width - 1;
- area.p1.y = tcm->height - 1;
-
- spin_lock(&(pvt->lock));
- fill_area(tcm, &area, NULL);
- spin_unlock(&(pvt->lock));
-
- for (i = 0; i < tcm->height; i++)
- kfree(pvt->map[i]);
- kfree(pvt->map);
- kfree(pvt);
-}
-
-/**
- * Reserve a 1D area in the container
- *
- * @param num_slots size of 1D area
- * @param area pointer to the area that will be populated with the
- * reserved area
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
- struct tcm_area *area)
-{
- s32 ret;
- struct tcm_area field = {0};
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
- spin_lock(&(pvt->lock));
-
- /* Scanning entire container */
- assign(&field, tcm->width - 1, tcm->height - 1, 0, 0);
-
- ret = scan_r2l_b2t_one_dim(tcm, num_slots, &field, area);
- if (!ret)
- /* update map */
- fill_area(tcm, area, area);
-
- spin_unlock(&(pvt->lock));
- return ret;
-}
-
-/**
- * Reserve a 2D area in the container
- *
- * @param w width
- * @param h height
- * @param area pointer to the area that will be populated with the reserved
- * area
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
- struct tcm_area *area)
-{
- s32 ret;
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
- /* not supporting more than 64 as alignment */
- if (align > 64)
- return -EINVAL;
-
- /* we prefer 1, 32 and 64 as alignment */
- align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
-
- spin_lock(&(pvt->lock));
- ret = scan_areas_and_find_fit(tcm, w, h, align, area);
- if (!ret)
- /* update map */
- fill_area(tcm, area, area);
-
- spin_unlock(&(pvt->lock));
- return ret;
-}
-
-/**
- * Unreserve a previously allocated 2D or 1D area
- * @param area area to be freed
- * @return 0 - success
- */
-static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
-{
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
- spin_lock(&(pvt->lock));
-
- /* check that this is in fact an existing area */
- WARN_ON(pvt->map[area->p0.x][area->p0.y] != area ||
- pvt->map[area->p1.x][area->p1.y] != area);
-
- /* Clear the contents of the associated tiles in the map */
- fill_area(tcm, area, NULL);
-
- spin_unlock(&(pvt->lock));
-
- return 0;
-}
-
-/**
- * Note: In general the cordinates in the scan field area relevant to the can
- * sweep directions. The scan origin (e.g. top-left corner) will always be
- * the p0 member of the field. Therfore, for a scan from top-left p0.x <= p1.x
- * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
- * <= p0.y
- */
-
-/**
- * Raster scan horizontally right to left from top to bottom to find a place for
- * a 2D area of given size inside a scan field.
- *
- * @param w width of desired area
- * @param h height of desired area
- * @param align desired area alignment
- * @param area pointer to the area that will be set to the best position
- * @param field area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *field, struct tcm_area *area)
-{
- s32 x, y;
- s16 start_x, end_x, start_y, end_y, found_x = -1;
- struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
- struct score best = {{0}, {0}, {0}, 0};
-
- start_x = field->p0.x;
- end_x = field->p1.x;
- start_y = field->p0.y;
- end_y = field->p1.y;
-
- /* check scan area co-ordinates */
- if (field->p0.x < field->p1.x ||
- field->p1.y < field->p0.y)
- return -EINVAL;
-
- /* check if allocation would fit in scan area */
- if (w > LEN(start_x, end_x) || h > LEN(end_y, start_y))
- return -ENOSPC;
-
- /* adjust start_x and end_y, as allocation would not fit beyond */
- start_x = ALIGN_DOWN(start_x - w + 1, align); /* - 1 to be inclusive */
- end_y = end_y - h + 1;
-
- /* check if allocation would still fit in scan area */
- if (start_x < end_x)
- return -ENOSPC;
-
- /* scan field top-to-bottom, right-to-left */
- for (y = start_y; y <= end_y; y++) {
- for (x = start_x; x >= end_x; x -= align) {
- if (is_area_free(map, x, y, w, h)) {
- found_x = x;
-
- /* update best candidate */
- if (update_candidate(tcm, x, y, w, h, field,
- CR_R2L_T2B, &best))
- goto done;
-
- /* change upper x bound */
- end_x = x + 1;
- break;
- } else if (map[x][y] && map[x][y]->is2d) {
- /* step over 2D areas */
- x = ALIGN(map[x][y]->p0.x - w + 1, align);
- }
- }
-
- /* break if you find a free area shouldering the scan field */
- if (found_x == start_x)
- break;
- }
-
- if (!best.a.tcm)
- return -ENOSPC;
-done:
- assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
- return 0;
-}
-
-/**
- * Raster scan horizontally left to right from top to bottom to find a place for
- * a 2D area of given size inside a scan field.
- *
- * @param w width of desired area
- * @param h height of desired area
- * @param align desired area alignment
- * @param area pointer to the area that will be set to the best position
- * @param field area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *field, struct tcm_area *area)
-{
- s32 x, y;
- s16 start_x, end_x, start_y, end_y, found_x = -1;
- struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
- struct score best = {{0}, {0}, {0}, 0};
-
- start_x = field->p0.x;
- end_x = field->p1.x;
- start_y = field->p0.y;
- end_y = field->p1.y;
-
- /* check scan area co-ordinates */
- if (field->p1.x < field->p0.x ||
- field->p1.y < field->p0.y)
- return -EINVAL;
-
- /* check if allocation would fit in scan area */
- if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
- return -ENOSPC;
-
- start_x = ALIGN(start_x, align);
-
- /* check if allocation would still fit in scan area */
- if (w > LEN(end_x, start_x))
- return -ENOSPC;
-
- /* adjust end_x and end_y, as allocation would not fit beyond */
- end_x = end_x - w + 1; /* + 1 to be inclusive */
- end_y = end_y - h + 1;
-
- /* scan field top-to-bottom, left-to-right */
- for (y = start_y; y <= end_y; y++) {
- for (x = start_x; x <= end_x; x += align) {
- if (is_area_free(map, x, y, w, h)) {
- found_x = x;
-
- /* update best candidate */
- if (update_candidate(tcm, x, y, w, h, field,
- CR_L2R_T2B, &best))
- goto done;
- /* change upper x bound */
- end_x = x - 1;
-
- break;
- } else if (map[x][y] && map[x][y]->is2d) {
- /* step over 2D areas */
- x = ALIGN_DOWN(map[x][y]->p1.x, align);
- }
- }
-
- /* break if you find a free area shouldering the scan field */
- if (found_x == start_x)
- break;
- }
-
- if (!best.a.tcm)
- return -ENOSPC;
-done:
- assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
- return 0;
-}
-
-/**
- * Raster scan horizontally right to left from bottom to top to find a place
- * for a 1D area of given size inside a scan field.
- *
- * @param num_slots size of desired area
- * @param align desired area alignment
- * @param area pointer to the area that will be set to the best
- * position
- * @param field area to scan (inclusive)
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
- struct tcm_area *field, struct tcm_area *area)
-{
- s32 found = 0;
- s16 x, y;
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
- struct tcm_area *p;
-
- /* check scan area co-ordinates */
- if (field->p0.y < field->p1.y)
- return -EINVAL;
-
- /**
- * Currently we only support full width 1D scan field, which makes sense
- * since 1D slot-ordering spans the full container width.
- */
- if (tcm->width != field->p0.x - field->p1.x + 1)
- return -EINVAL;
-
- /* check if allocation would fit in scan area */
- if (num_slots > tcm->width * LEN(field->p0.y, field->p1.y))
- return -ENOSPC;
-
- x = field->p0.x;
- y = field->p0.y;
-
- /* find num_slots consecutive free slots to the left */
- while (found < num_slots) {
- if (y < 0)
- return -ENOSPC;
-
- /* remember bottom-right corner */
- if (found == 0) {
- area->p1.x = x;
- area->p1.y = y;
- }
-
- /* skip busy regions */
- p = pvt->map[x][y];
- if (p) {
- /* move to left of 2D areas, top left of 1D */
- x = p->p0.x;
- if (!p->is2d)
- y = p->p0.y;
-
- /* start over */
- found = 0;
- } else {
- /* count consecutive free slots */
- found++;
- if (found == num_slots)
- break;
- }
-
- /* move to the left */
- if (x == 0)
- y--;
- x = (x ? : tcm->width) - 1;
-
- }
-
- /* set top-left corner */
- area->p0.x = x;
- area->p0.y = y;
- return 0;
-}
-
-/**
- * Find a place for a 2D area of given size inside a scan field based on its
- * alignment needs.
- *
- * @param w width of desired area
- * @param h height of desired area
- * @param align desired area alignment
- * @param area pointer to the area that will be set to the best position
- *
- * @return 0 on success, non-0 error value on failure.
- */
-static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
- struct tcm_area *area)
-{
- s32 ret = 0;
- struct tcm_area field = {0};
- u16 boundary_x, boundary_y;
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
- if (align > 1) {
- /* prefer top-left corner */
- boundary_x = pvt->div_pt.x - 1;
- boundary_y = pvt->div_pt.y - 1;
-
- /* expand width and height if needed */
- if (w > pvt->div_pt.x)
- boundary_x = tcm->width - 1;
- if (h > pvt->div_pt.y)
- boundary_y = tcm->height - 1;
-
- assign(&field, 0, 0, boundary_x, boundary_y);
- ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
-
- /* scan whole container if failed, but do not scan 2x */
- if (ret != 0 && (boundary_x != tcm->width - 1 ||
- boundary_y != tcm->height - 1)) {
- /* scan the entire container if nothing found */
- assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
- ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
- }
- } else if (align == 1) {
- /* prefer top-right corner */
- boundary_x = pvt->div_pt.x;
- boundary_y = pvt->div_pt.y - 1;
-
- /* expand width and height if needed */
- if (w > (tcm->width - pvt->div_pt.x))
- boundary_x = 0;
- if (h > pvt->div_pt.y)
- boundary_y = tcm->height - 1;
-
- assign(&field, tcm->width - 1, 0, boundary_x, boundary_y);
- ret = scan_r2l_t2b(tcm, w, h, align, &field, area);
-
- /* scan whole container if failed, but do not scan 2x */
- if (ret != 0 && (boundary_x != 0 ||
- boundary_y != tcm->height - 1)) {
- /* scan the entire container if nothing found */
- assign(&field, tcm->width - 1, 0, 0, tcm->height - 1);
- ret = scan_r2l_t2b(tcm, w, h, align, &field,
- area);
- }
- }
-
- return ret;
-}
-
-/* check if an entire area is free */
-static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
-{
- u16 x = 0, y = 0;
- for (y = y0; y < y0 + h; y++) {
- for (x = x0; x < x0 + w; x++) {
- if (map[x][y])
- return false;
- }
- }
- return true;
-}
-
-/* fills an area with a parent tcm_area */
-static void fill_area(struct tcm *tcm, struct tcm_area *area,
- struct tcm_area *parent)
-{
- s32 x, y;
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
- struct tcm_area a, a_;
-
- /* set area's tcm; otherwise, enumerator considers it invalid */
- area->tcm = tcm;
-
- tcm_for_each_slice(a, *area, a_) {
- for (x = a.p0.x; x <= a.p1.x; ++x)
- for (y = a.p0.y; y <= a.p1.y; ++y)
- pvt->map[x][y] = parent;
-
- }
-}
-
-/**
- * Compares a candidate area to the current best area, and if it is a better
- * fit, it updates the best to this one.
- *
- * @param x0, y0, w, h top, left, width, height of candidate area
- * @param field scan field
- * @param criteria scan criteria
- * @param best best candidate and its scores
- *
- * @return 1 (true) if the candidate area is known to be the final best, so no
- * more searching should be performed
- */
-static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
- struct tcm_area *field, s32 criteria,
- struct score *best)
-{
- struct score me; /* score for area */
-
- /*
- * NOTE: For horizontal bias we always give the first found, because our
- * scan is horizontal-raster-based and the first candidate will always
- * have the horizontal bias.
- */
- bool first = criteria & CR_BIAS_HORIZONTAL;
-
- assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
-
- /* calculate score for current candidate */
- if (!first) {
- get_neighbor_stats(tcm, &me.a, &me.n);
- me.neighs = me.n.edge + me.n.busy;
- get_nearness_factor(field, &me.a, &me.f);
- }
-
- /* the 1st candidate is always the best */
- if (!best->a.tcm)
- goto better;
-
- BUG_ON(first);
-
- /* diagonal balance check */
- if ((criteria & CR_DIAGONAL_BALANCE) &&
- best->neighs <= me.neighs &&
- (best->neighs < me.neighs ||
- /* this implies that neighs and occupied match */
- best->n.busy < me.n.busy ||
- (best->n.busy == me.n.busy &&
- /* check the nearness factor */
- best->f.x + best->f.y > me.f.x + me.f.y)))
- goto better;
-
- /* not better, keep going */
- return 0;
-
-better:
- /* save current area as best */
- memcpy(best, &me, sizeof(me));
- best->a.tcm = tcm;
- return first;
-}
-
-/**
- * Calculate the nearness factor of an area in a search field. The nearness
- * factor is smaller if the area is closer to the search origin.
- */
-static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
- struct nearness_factor *nf)
-{
- /**
- * Using signed math as field coordinates may be reversed if
- * search direction is right-to-left or bottom-to-top.
- */
- nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
- (field->p1.x - field->p0.x);
- nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
- (field->p1.y - field->p0.y);
-}
-
-/* get neighbor statistics */
-static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
- struct neighbor_stats *stat)
-{
- s16 x = 0, y = 0;
- struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
-
- /* Clearing any exisiting values */
- memset(stat, 0, sizeof(*stat));
-
- /* process top & bottom edges */
- for (x = area->p0.x; x <= area->p1.x; x++) {
- if (area->p0.y == 0)
- stat->edge++;
- else if (pvt->map[x][area->p0.y - 1])
- stat->busy++;
-
- if (area->p1.y == tcm->height - 1)
- stat->edge++;
- else if (pvt->map[x][area->p1.y + 1])
- stat->busy++;
- }
-
- /* process left & right edges */
- for (y = area->p0.y; y <= area->p1.y; ++y) {
- if (area->p0.x == 0)
- stat->edge++;
- else if (pvt->map[area->p0.x - 1][y])
- stat->busy++;
-
- if (area->p1.x == tcm->width - 1)
- stat->edge++;
- else if (pvt->map[area->p1.x + 1][y])
- stat->busy++;
- }
-}
diff --git a/drivers/staging/omapdrm/tcm-sita.h b/drivers/staging/omapdrm/tcm-sita.h
deleted file mode 100644
index 0444f868671..00000000000
--- a/drivers/staging/omapdrm/tcm-sita.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * tcm_sita.h
- *
- * SImple Tiler Allocator (SiTA) private structures.
- *
- * Author: Ravi Ramachandra <r.ramachandra@ti.com>
- *
- * Copyright (C) 2009-2011 Texas Instruments, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of Texas Instruments Incorporated nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _TCM_SITA_H
-#define _TCM_SITA_H
-
-#include "tcm.h"
-
-/* length between two coordinates */
-#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
-
-enum criteria {
- CR_MAX_NEIGHS = 0x01,
- CR_FIRST_FOUND = 0x10,
- CR_BIAS_HORIZONTAL = 0x20,
- CR_BIAS_VERTICAL = 0x40,
- CR_DIAGONAL_BALANCE = 0x80
-};
-
-/* nearness to the beginning of the search field from 0 to 1000 */
-struct nearness_factor {
- s32 x;
- s32 y;
-};
-
-/*
- * Statistics on immediately neighboring slots. Edge is the number of
- * border segments that are also border segments of the scan field. Busy
- * refers to the number of neighbors that are occupied.
- */
-struct neighbor_stats {
- u16 edge;
- u16 busy;
-};
-
-/* structure to keep the score of a potential allocation */
-struct score {
- struct nearness_factor f;
- struct neighbor_stats n;
- struct tcm_area a;
- u16 neighs; /* number of busy neighbors */
-};
-
-struct sita_pvt {
- spinlock_t lock; /* spinlock to protect access */
- struct tcm_pt div_pt; /* divider point splitting container */
- struct tcm_area ***map; /* pointers to the parent area for each slot */
-};
-
-/* assign coordinates to area */
-static inline
-void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
-{
- a->p0.x = x0;
- a->p0.y = y0;
- a->p1.x = x1;
- a->p1.y = y1;
-}
-
-#endif
diff --git a/drivers/staging/omapdrm/tcm.h b/drivers/staging/omapdrm/tcm.h
deleted file mode 100644
index a8d5ce47686..00000000000
--- a/drivers/staging/omapdrm/tcm.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * tcm.h
- *
- * TILER container manager specification and support functions for TI
- * TILER driver.
- *
- * Author: Lajos Molnar <molnar@ti.com>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of Texas Instruments Incorporated nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TCM_H
-#define TCM_H
-
-struct tcm;
-
-/* point */
-struct tcm_pt {
- u16 x;
- u16 y;
-};
-
-/* 1d or 2d area */
-struct tcm_area {
- bool is2d; /* whether area is 1d or 2d */
- struct tcm *tcm; /* parent */
- struct tcm_pt p0;
- struct tcm_pt p1;
-};
-
-struct tcm {
- u16 width, height; /* container dimensions */
- int lut_id; /* Lookup table identifier */
-
- unsigned int y_offset; /* offset to use for y coordinates */
-
- /* 'pvt' structure shall contain any tcm details (attr) along with
- linked list of allocated areas and mutex for mutually exclusive access
- to the list. It may also contain copies of width and height to notice
- any changes to the publicly available width and height fields. */
- void *pvt;
-
- /* function table */
- s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
- struct tcm_area *area);
- s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area);
- s32 (*free) (struct tcm *tcm, struct tcm_area *area);
- void (*deinit) (struct tcm *tcm);
-};
-
-/*=============================================================================
- BASIC TILER CONTAINER MANAGER INTERFACE
-=============================================================================*/
-
-/*
- * NOTE:
- *
- * Since some basic parameter checking is done outside the TCM algorithms,
- * TCM implementation do NOT have to check the following:
- *
- * area pointer is NULL
- * width and height fits within container
- * number of pages is more than the size of the container
- *
- */
-
-struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr);
-
-
-/**
- * Deinitialize tiler container manager.
- *
- * @param tcm Pointer to container manager.
- *
- * @return 0 on success, non-0 error value on error. The call
- * should free as much memory as possible and meaningful
- * even on failure. Some error codes: -ENODEV: invalid
- * manager.
- */
-static inline void tcm_deinit(struct tcm *tcm)
-{
- if (tcm)
- tcm->deinit(tcm);
-}
-
-/**
- * Reserves a 2D area in the container.
- *
- * @param tcm Pointer to container manager.
- * @param height Height(in pages) of area to be reserved.
- * @param width Width(in pages) of area to be reserved.
- * @param align Alignment requirement for top-left corner of area. Not
- * all values may be supported by the container manager,
- * but it must support 0 (1), 32 and 64.
- * 0 value is equivalent to 1.
- * @param area Pointer to where the reserved area should be stored.
- *
- * @return 0 on success. Non-0 error code on failure. Also,
- * the tcm field of the area will be set to NULL on
- * failure. Some error codes: -ENODEV: invalid manager,
- * -EINVAL: invalid area, -ENOMEM: not enough space for
- * allocation.
- */
-static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
- u16 align, struct tcm_area *area)
-{
- /* perform rudimentary error checking */
- s32 res = tcm == NULL ? -ENODEV :
- (area == NULL || width == 0 || height == 0 ||
- /* align must be a 2 power */
- (align & (align - 1))) ? -EINVAL :
- (height > tcm->height || width > tcm->width) ? -ENOMEM : 0;
-
- if (!res) {
- area->is2d = true;
- res = tcm->reserve_2d(tcm, height, width, align, area);
- area->tcm = res ? NULL : tcm;
- }
-
- return res;
-}
-
-/**
- * Reserves a 1D area in the container.
- *
- * @param tcm Pointer to container manager.
- * @param slots Number of (contiguous) slots to reserve.
- * @param area Pointer to where the reserved area should be stored.
- *
- * @return 0 on success. Non-0 error code on failure. Also,
- * the tcm field of the area will be set to NULL on
- * failure. Some error codes: -ENODEV: invalid manager,
- * -EINVAL: invalid area, -ENOMEM: not enough space for
- * allocation.
- */
-static inline s32 tcm_reserve_1d(struct tcm *tcm, u32 slots,
- struct tcm_area *area)
-{
- /* perform rudimentary error checking */
- s32 res = tcm == NULL ? -ENODEV :
- (area == NULL || slots == 0) ? -EINVAL :
- slots > (tcm->width * (u32) tcm->height) ? -ENOMEM : 0;
-
- if (!res) {
- area->is2d = false;
- res = tcm->reserve_1d(tcm, slots, area);
- area->tcm = res ? NULL : tcm;
- }
-
- return res;
-}
-
-/**
- * Free a previously reserved area from the container.
- *
- * @param area Pointer to area reserved by a prior call to
- * tcm_reserve_1d or tcm_reserve_2d call, whether
- * it was successful or not. (Note: all fields of
- * the structure must match.)
- *
- * @return 0 on success. Non-0 error code on failure. Also, the tcm
- * field of the area is set to NULL on success to avoid subsequent
- * freeing. This call will succeed even if supplying
- * the area from a failed reserved call.
- */
-static inline s32 tcm_free(struct tcm_area *area)
-{
- s32 res = 0; /* free succeeds by default */
-
- if (area && area->tcm) {
- res = area->tcm->free(area->tcm, area);
- if (res == 0)
- area->tcm = NULL;
- }
-
- return res;
-}
-
-/*=============================================================================
- HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER
-=============================================================================*/
-
-/**
- * This method slices off the topmost 2D slice from the parent area, and stores
- * it in the 'slice' parameter. The 'parent' parameter will get modified to
- * contain the remaining portion of the area. If the whole parent area can
- * fit in a 2D slice, its tcm pointer is set to NULL to mark that it is no
- * longer a valid area.
- *
- * @param parent Pointer to a VALID parent area that will get modified
- * @param slice Pointer to the slice area that will get modified
- */
-static inline void tcm_slice(struct tcm_area *parent, struct tcm_area *slice)
-{
- *slice = *parent;
-
- /* check if we need to slice */
- if (slice->tcm && !slice->is2d &&
- slice->p0.y != slice->p1.y &&
- (slice->p0.x || (slice->p1.x != slice->tcm->width - 1))) {
- /* set end point of slice (start always remains) */
- slice->p1.x = slice->tcm->width - 1;
- slice->p1.y = (slice->p0.x) ? slice->p0.y : slice->p1.y - 1;
- /* adjust remaining area */
- parent->p0.x = 0;
- parent->p0.y = slice->p1.y + 1;
- } else {
- /* mark this as the last slice */
- parent->tcm = NULL;
- }
-}
-
-/* Verify if a tcm area is logically valid */
-static inline bool tcm_area_is_valid(struct tcm_area *area)
-{
- return area && area->tcm &&
- /* coordinate bounds */
- area->p1.x < area->tcm->width &&
- area->p1.y < area->tcm->height &&
- area->p0.y <= area->p1.y &&
- /* 1D coordinate relationship + p0.x check */
- ((!area->is2d &&
- area->p0.x < area->tcm->width &&
- area->p0.x + area->p0.y * area->tcm->width <=
- area->p1.x + area->p1.y * area->tcm->width) ||
- /* 2D coordinate relationship */
- (area->is2d &&
- area->p0.x <= area->p1.x));
-}
-
-/* see if a coordinate is within an area */
-static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
-{
- u16 i;
-
- if (a->is2d) {
- return p->x >= a->p0.x && p->x <= a->p1.x &&
- p->y >= a->p0.y && p->y <= a->p1.y;
- } else {
- i = p->x + p->y * a->tcm->width;
- return i >= a->p0.x + a->p0.y * a->tcm->width &&
- i <= a->p1.x + a->p1.y * a->tcm->width;
- }
-}
-
-/* calculate area width */
-static inline u16 __tcm_area_width(struct tcm_area *area)
-{
- return area->p1.x - area->p0.x + 1;
-}
-
-/* calculate area height */
-static inline u16 __tcm_area_height(struct tcm_area *area)
-{
- return area->p1.y - area->p0.y + 1;
-}
-
-/* calculate number of slots in an area */
-static inline u16 __tcm_sizeof(struct tcm_area *area)
-{
- return area->is2d ?
- __tcm_area_width(area) * __tcm_area_height(area) :
- (area->p1.x - area->p0.x + 1) + (area->p1.y - area->p0.y) *
- area->tcm->width;
-}
-#define tcm_sizeof(area) __tcm_sizeof(&(area))
-#define tcm_awidth(area) __tcm_area_width(&(area))
-#define tcm_aheight(area) __tcm_area_height(&(area))
-#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
-
-/* limit a 1D area to the first N pages */
-static inline s32 tcm_1d_limit(struct tcm_area *a, u32 num_pg)
-{
- if (__tcm_sizeof(a) < num_pg)
- return -ENOMEM;
- if (!num_pg)
- return -EINVAL;
-
- a->p1.x = (a->p0.x + num_pg - 1) % a->tcm->width;
- a->p1.y = a->p0.y + ((a->p0.x + num_pg - 1) / a->tcm->width);
- return 0;
-}
-
-/**
- * Iterate through 2D slices of a valid area. Behaves
- * syntactically as a for(;;) statement.
- *
- * @param var Name of a local variable of type 'struct
- * tcm_area *' that will get modified to
- * contain each slice.
- * @param area Pointer to the VALID parent area. This
- * structure will not get modified
- * throughout the loop.
- *
- */
-#define tcm_for_each_slice(var, area, safe) \
- for (safe = area, \
- tcm_slice(&safe, &var); \
- var.tcm; tcm_slice(&safe, &var))
-
-#endif