diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 13:17:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-05 13:17:26 -0400 |
commit | a09e9a7a4b907f2dfa9bdb2b98a1828ab4b340b2 (patch) | |
tree | c7a2df4e887573648eeaf8f7939889046990d3f6 /drivers/gpu/drm/tilcdc | |
parent | 9ab073bc45b8b523cc39658925bb44bef35ca657 (diff) | |
parent | 86a7e1224a68511d3a1ae0b7e11581b9d37723ae (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.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 @@ | |||
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 | ||
43 | static void unref_worker(struct work_struct *work) | 42 | static 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 | ||
157 | static int tilcdc_crtc_page_flip(struct drm_crtc *crtc, | 149 | static 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 | ||
75 | static 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 | |||
75 | static const struct drm_encoder_funcs slave_encoder_funcs = { | 100 | static const struct drm_encoder_funcs slave_encoder_funcs = { |
76 | .destroy = slave_encoder_destroy, | 101 | .destroy = slave_encoder_destroy, |
77 | }; | 102 | }; |
78 | 103 | ||
79 | static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { | 104 | static 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, |