diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 19:17:26 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 19:17:26 +0200 |
commit | a09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2 (patch) | |
tree | c7a2df4e887573648eeaf8f7939889046990d3f6 /drivers/gpu/drm/tilcdc | |
parent | Merge tag 'fbdev-3.12' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba... (diff) | |
parent | Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/g... (diff) | |
download | linux-a09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2.tar.xz linux-a09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2.zip |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm tree changes from Dave Airlie:
"This is the main drm pull request, I have some overlap with sound and
arm-soc, the sound patch is acked and may conflict based on -next
reports but should be a trivial fixup, which I'll leave to you!
Highlights:
- new drivers:
MSM driver from Rob Clark
- non-drm:
switcheroo and hdmi audio driver support for secondary GPU
poweroff, so drivers can use runtime PM to poweroff the GPUs. This
can save 5 or 6W on some optimus laptops.
- drm core:
combined GEM and TTM VMA manager
per-filp mmap permission tracking
initial rendernode support (via a runtime enable for now, until we get api stable),
remove old proc support,
lots of cleanups of legacy code
hdmi vendor infoframes and 4k modes
lots of gem/prime locking and races fixes
async pageflip scaffolding
drm bridge objects
- i915:
Haswell PC8+ support and eLLC support, HDMI 4K support, initial
per-process VMA pieces, watermark reworks, convert to generic hdmi
infoframes, encoder reworking, fastboot support,
- radeon:
CIK PM support, remove 3d blit code in favour of DMA engines,
Berlin GPU support, HDMI audio fixes
- nouveau:
secondary GPU power down support for optimus laptops, lots of
fixes, use MSI, VP3 engine support
- exynos:
runtime pm support for g2d, DT support, remove non-DT,
- tda998x i2c driver:
lots of fixes for sync issues
- gma500:
lots of cleanups
- rcar:
add LVDS support, fbdev emulation,
- tegra:
just minor fixes"
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (684 commits)
drm/exynos: Fix build error with exynos_drm_connector.c
drm/exynos: Remove non-DT support in exynos_drm_fimd
drm/exynos: Remove non-DT support in exynos_hdmi
drm/exynos: Remove non-DT support in exynos_drm_g2d
drm/exynos: Remove non-DT support in exynos_hdmiphy
drm/exynos: Remove non-DT support in exynos_ddc
drm/exynos: Make Exynos DRM drivers depend on OF
drm/exynos: Consider fallback option to allocation fail
drm/exynos: fimd: move platform data parsing to separate function
drm/exynos: fimd: get signal polarities from device tree
drm/exynos: fimd: replace struct fb_videomode with videomode
drm/exynos: check a pixel format to a particular window layer
drm/exynos: fix fimd pixel format setting
drm/exynos: Add NULL pointer check
drm/exynos: Remove redundant error messages
drm/exynos: Add missing of.h header include
drm/exynos: Remove redundant NULL check in exynos_drm_buf
drm/exynos: add device tree support for rotator
drm/exynos: Add missing includes
drm/exynos: add runtime pm interfaces to g2d driver
...
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 43 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_slave.c | 27 |
3 files changed, 47 insertions, 26 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 7418dcd986d3..d36efc13b16f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -15,7 +15,7 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/kfifo.h> +#include "drm_flip_work.h" #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -35,21 +35,18 @@ struct tilcdc_crtc { struct drm_framebuffer *scanout[2]; /* for deferred fb unref's: */ - DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *); - struct work_struct work; + struct drm_flip_work unref_work; }; #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) -static void unref_worker(struct work_struct *work) +static void unref_worker(struct drm_flip_work *work, void *val) { struct tilcdc_crtc *tilcdc_crtc = - container_of(work, struct tilcdc_crtc, work); + container_of(work, struct tilcdc_crtc, unref_work); struct drm_device *dev = tilcdc_crtc->base.dev; - struct drm_framebuffer *fb; mutex_lock(&dev->mode_config.mutex); - while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb)) - drm_framebuffer_unreference(fb); + drm_framebuffer_unreference(val); mutex_unlock(&dev->mode_config.mutex); } @@ -68,19 +65,14 @@ static void set_scanout(struct drm_crtc *crtc, int n) }; struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; + struct tilcdc_drm_private *priv = dev->dev_private; pm_runtime_get_sync(dev->dev); tilcdc_write(dev, base_reg[n], tilcdc_crtc->start); tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end); if (tilcdc_crtc->scanout[n]) { - if (kfifo_put(&tilcdc_crtc->unref_fifo, - (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) { - struct tilcdc_drm_private *priv = dev->dev_private; - queue_work(priv->wq, &tilcdc_crtc->work); - } else { - dev_err(dev->dev, "unref fifo full!\n"); - drm_framebuffer_unreference(tilcdc_crtc->scanout[n]); - } + drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]); + drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq); } tilcdc_crtc->scanout[n] = crtc->fb; drm_framebuffer_reference(tilcdc_crtc->scanout[n]); @@ -149,14 +141,15 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); drm_crtc_cleanup(crtc); - WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo)); - kfifo_free(&tilcdc_crtc->unref_fifo); + drm_flip_work_cleanup(&tilcdc_crtc->unref_work); + kfree(tilcdc_crtc); } static int tilcdc_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -379,7 +372,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); - if (mode->flags & DRM_MODE_FLAG_NHSYNC) + /* + * use value from adjusted_mode here as this might have been + * changed as part of the fixup for slave encoders to solve the + * issue where tilcdc timings are not VESA compliant + */ + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); else tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); @@ -666,14 +664,13 @@ struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF; init_waitqueue_head(&tilcdc_crtc->frame_done_wq); - ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL); + ret = drm_flip_work_init(&tilcdc_crtc->unref_work, 16, + "unref", unref_worker); if (ret) { dev_err(dev->dev, "could not allocate unref FIFO\n"); goto fail; } - INIT_WORK(&tilcdc_crtc->work, unref_worker); - ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs); if (ret < 0) goto fail; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 40b71da5a214..116da199b942 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -497,7 +497,6 @@ static const struct file_operations fops = { #endif .poll = drm_poll, .read = drm_read, - .fasync = drm_fasync, .llseek = no_llseek, .mmap = drm_gem_cma_mmap, }; @@ -519,7 +518,7 @@ static struct drm_driver tilcdc_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, - .dumb_destroy = drm_gem_cma_dumb_destroy, + .dumb_destroy = drm_gem_dumb_destroy, #ifdef CONFIG_DEBUG_FS .debugfs_init = tilcdc_debugfs_init, .debugfs_cleanup = tilcdc_debugfs_cleanup, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index a19f657dfa59..595068ba2d5e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -72,13 +72,38 @@ static void slave_encoder_prepare(struct drm_encoder *encoder) tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info); } +static bool slave_encoder_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* + * tilcdc does not generate VESA-complient sync but aligns + * VS on the second edge of HS instead of first edge. + * We use adjusted_mode, to fixup sync by aligning both rising + * edges and add HSKEW offset to let the slave encoder fix it up. + */ + adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; + adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; + + if (mode->flags & DRM_MODE_FLAG_NHSYNC) { + adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; + } else { + adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; + adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; + } + + return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); +} + + static const struct drm_encoder_funcs slave_encoder_funcs = { .destroy = slave_encoder_destroy, }; static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { .dpms = drm_i2c_encoder_dpms, - .mode_fixup = drm_i2c_encoder_mode_fixup, + .mode_fixup = slave_encoder_fixup, .prepare = slave_encoder_prepare, .commit = drm_i2c_encoder_commit, .mode_set = drm_i2c_encoder_mode_set, |