aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tilcdc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 13:17:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 13:17:26 -0400
commita09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2 (patch)
treec7a2df4e887573648eeaf8f7939889046990d3f6 /drivers/gpu/drm/tilcdc
parent9ab073bc45b8b523cc39658925bb44bef35ca657 (diff)
parent86a7e1224a68511d3a1ae0b7e11581b9d37723ae (diff)
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.c43
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c3
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_slave.c27
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 @@
15 * this program. If not, see <http://www.gnu.org/licenses/>. 15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <linux/kfifo.h> 18#include "drm_flip_work.h"
19 19
20#include "tilcdc_drv.h" 20#include "tilcdc_drv.h"
21#include "tilcdc_regs.h" 21#include "tilcdc_regs.h"
@@ -35,21 +35,18 @@ struct tilcdc_crtc {
35 struct drm_framebuffer *scanout[2]; 35 struct drm_framebuffer *scanout[2];
36 36
37 /* for deferred fb unref's: */ 37 /* for deferred fb unref's: */
38 DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *); 38 struct drm_flip_work unref_work;
39 struct work_struct work;
40}; 39};
41#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) 40#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
42 41
43static void unref_worker(struct work_struct *work) 42static void unref_worker(struct drm_flip_work *work, void *val)
44{ 43{
45 struct tilcdc_crtc *tilcdc_crtc = 44 struct tilcdc_crtc *tilcdc_crtc =
46 container_of(work, struct tilcdc_crtc, work); 45 container_of(work, struct tilcdc_crtc, unref_work);
47 struct drm_device *dev = tilcdc_crtc->base.dev; 46 struct drm_device *dev = tilcdc_crtc->base.dev;
48 struct drm_framebuffer *fb;
49 47
50 mutex_lock(&dev->mode_config.mutex); 48 mutex_lock(&dev->mode_config.mutex);
51 while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb)) 49 drm_framebuffer_unreference(val);
52 drm_framebuffer_unreference(fb);
53 mutex_unlock(&dev->mode_config.mutex); 50 mutex_unlock(&dev->mode_config.mutex);
54} 51}
55 52
@@ -68,19 +65,14 @@ static void set_scanout(struct drm_crtc *crtc, int n)
68 }; 65 };
69 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 66 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
70 struct drm_device *dev = crtc->dev; 67 struct drm_device *dev = crtc->dev;
68 struct tilcdc_drm_private *priv = dev->dev_private;
71 69
72 pm_runtime_get_sync(dev->dev); 70 pm_runtime_get_sync(dev->dev);
73 tilcdc_write(dev, base_reg[n], tilcdc_crtc->start); 71 tilcdc_write(dev, base_reg[n], tilcdc_crtc->start);
74 tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end); 72 tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end);
75 if (tilcdc_crtc->scanout[n]) { 73 if (tilcdc_crtc->scanout[n]) {
76 if (kfifo_put(&tilcdc_crtc->unref_fifo, 74 drm_flip_work_queue(&tilcdc_crtc->unref_work, tilcdc_crtc->scanout[n]);
77 (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) { 75 drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
78 struct tilcdc_drm_private *priv = dev->dev_private;
79 queue_work(priv->wq, &tilcdc_crtc->work);
80 } else {
81 dev_err(dev->dev, "unref fifo full!\n");
82 drm_framebuffer_unreference(tilcdc_crtc->scanout[n]);
83 }
84 } 76 }
85 tilcdc_crtc->scanout[n] = crtc->fb; 77 tilcdc_crtc->scanout[n] = crtc->fb;
86 drm_framebuffer_reference(tilcdc_crtc->scanout[n]); 78 drm_framebuffer_reference(tilcdc_crtc->scanout[n]);
@@ -149,14 +141,15 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
149 WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); 141 WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON);
150 142
151 drm_crtc_cleanup(crtc); 143 drm_crtc_cleanup(crtc);
152 WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo)); 144 drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
153 kfifo_free(&tilcdc_crtc->unref_fifo); 145
154 kfree(tilcdc_crtc); 146 kfree(tilcdc_crtc);
155} 147}
156 148
157static int tilcdc_crtc_page_flip(struct drm_crtc *crtc, 149static int tilcdc_crtc_page_flip(struct drm_crtc *crtc,
158 struct drm_framebuffer *fb, 150 struct drm_framebuffer *fb,
159 struct drm_pending_vblank_event *event) 151 struct drm_pending_vblank_event *event,
152 uint32_t page_flip_flags)
160{ 153{
161 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); 154 struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
162 struct drm_device *dev = crtc->dev; 155 struct drm_device *dev = crtc->dev;
@@ -379,7 +372,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc,
379 else 372 else
380 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); 373 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE);
381 374
382 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 375 /*
376 * use value from adjusted_mode here as this might have been
377 * changed as part of the fixup for slave encoders to solve the
378 * issue where tilcdc timings are not VESA compliant
379 */
380 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
383 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); 381 tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC);
384 else 382 else
385 tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); 383 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)
666 tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF; 664 tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF;
667 init_waitqueue_head(&tilcdc_crtc->frame_done_wq); 665 init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
668 666
669 ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL); 667 ret = drm_flip_work_init(&tilcdc_crtc->unref_work, 16,
668 "unref", unref_worker);
670 if (ret) { 669 if (ret) {
671 dev_err(dev->dev, "could not allocate unref FIFO\n"); 670 dev_err(dev->dev, "could not allocate unref FIFO\n");
672 goto fail; 671 goto fail;
673 } 672 }
674 673
675 INIT_WORK(&tilcdc_crtc->work, unref_worker);
676
677 ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs); 674 ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs);
678 if (ret < 0) 675 if (ret < 0)
679 goto fail; 676 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 = {
497#endif 497#endif
498 .poll = drm_poll, 498 .poll = drm_poll,
499 .read = drm_read, 499 .read = drm_read,
500 .fasync = drm_fasync,
501 .llseek = no_llseek, 500 .llseek = no_llseek,
502 .mmap = drm_gem_cma_mmap, 501 .mmap = drm_gem_cma_mmap,
503}; 502};
@@ -519,7 +518,7 @@ static struct drm_driver tilcdc_driver = {
519 .gem_vm_ops = &drm_gem_cma_vm_ops, 518 .gem_vm_ops = &drm_gem_cma_vm_ops,
520 .dumb_create = drm_gem_cma_dumb_create, 519 .dumb_create = drm_gem_cma_dumb_create,
521 .dumb_map_offset = drm_gem_cma_dumb_map_offset, 520 .dumb_map_offset = drm_gem_cma_dumb_map_offset,
522 .dumb_destroy = drm_gem_cma_dumb_destroy, 521 .dumb_destroy = drm_gem_dumb_destroy,
523#ifdef CONFIG_DEBUG_FS 522#ifdef CONFIG_DEBUG_FS
524 .debugfs_init = tilcdc_debugfs_init, 523 .debugfs_init = tilcdc_debugfs_init,
525 .debugfs_cleanup = tilcdc_debugfs_cleanup, 524 .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)
72 tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info); 72 tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info);
73} 73}
74 74
75static bool slave_encoder_fixup(struct drm_encoder *encoder,
76 const struct drm_display_mode *mode,
77 struct drm_display_mode *adjusted_mode)
78{
79 /*
80 * tilcdc does not generate VESA-complient sync but aligns
81 * VS on the second edge of HS instead of first edge.
82 * We use adjusted_mode, to fixup sync by aligning both rising
83 * edges and add HSKEW offset to let the slave encoder fix it up.
84 */
85 adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
86 adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
87
88 if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
89 adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
90 adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
91 } else {
92 adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
93 adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
94 }
95
96 return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode);
97}
98
99
75static const struct drm_encoder_funcs slave_encoder_funcs = { 100static const struct drm_encoder_funcs slave_encoder_funcs = {
76 .destroy = slave_encoder_destroy, 101 .destroy = slave_encoder_destroy,
77}; 102};
78 103
79static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { 104static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = {
80 .dpms = drm_i2c_encoder_dpms, 105 .dpms = drm_i2c_encoder_dpms,
81 .mode_fixup = drm_i2c_encoder_mode_fixup, 106 .mode_fixup = slave_encoder_fixup,
82 .prepare = slave_encoder_prepare, 107 .prepare = slave_encoder_prepare,
83 .commit = drm_i2c_encoder_commit, 108 .commit = drm_i2c_encoder_commit,
84 .mode_set = drm_i2c_encoder_mode_set, 109 .mode_set = drm_i2c_encoder_mode_set,