From f43f627d2f17e95c78647eeddf968d12f5c286b1 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Feb 2013 13:37:20 +0000 Subject: PM: make VT switching to the suspend console optional v3 KMS drivers can potentially restore the display configuration without userspace help. Such drivers can can call a new funciton, pm_vt_switch_required(false) if they support this feature. In that case, the PM layer won't VT switch to the suspend console at suspend time and then back to the original VT on resume, but rather leave things alone for a nicer looking suspend and resume sequence. v2: make a function so we can handle multiple drivers (Alan) v3: use a list to track device requests (Rafael) v4: Squash in build fix from Jesse for CONFIG_VT_CONSOLE_SLEEP=n v5: Squash in patch from Wu Fengguang to add a few missing static qualifiers. v6: Add missing EXPORT_SYMBOL. Signed-off-by: Jesse Barnes Reviewed-by: Rafael J. Wysocki (v3) Signed-off-by: Daniel Vetter --- include/linux/pm.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 03d7bb145311..e5da2f353e8f 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -35,6 +35,19 @@ extern void (*pm_idle)(void); extern void (*pm_power_off)(void); extern void (*pm_power_off_prepare)(void); +struct device; /* we have a circular dep with device.h */ +#ifdef CONFIG_VT_CONSOLE_SLEEP +extern void pm_vt_switch_required(struct device *dev, bool required); +extern void pm_vt_switch_unregister(struct device *dev); +#else +static inline void pm_vt_switch_required(struct device *dev, bool required) +{ +} +static inline void pm_vt_switch_unregister(struct device *dev) +{ +} +#endif /* CONFIG_VT_CONSOLE_SLEEP */ + /* * Device power management */ -- cgit v1.2.3 From 3cf2667b9f8b2c2fe298a427deb399e52321da6b Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 4 Feb 2013 13:37:21 +0000 Subject: fb: add support for drivers not needing VT switch at suspend/resume time Use the new PM routines to indicate whether we need to VT switch at suspend and resume time. When a new driver is bound, set its flag accordingly, and when unbound, remove it from the PM's console tracking list. Signed-off-by: Jesse Barnes Acked-by: Rafael J. Wysocki Signed-off-by: Daniel Vetter --- drivers/video/fbmem.c | 7 +++++++ include/linux/fb.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'include') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index dc61c12ecf8c..2af7153da2e4 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1645,6 +1645,11 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (!fb_info->modelist.prev || !fb_info->modelist.next) INIT_LIST_HEAD(&fb_info->modelist); + if (fb_info->skip_vt_switch) + pm_vt_switch_required(fb_info->dev, false); + else + pm_vt_switch_required(fb_info->dev, true); + fb_var_to_videomode(&mode, &fb_info->var); fb_add_videomode(&mode, &fb_info->modelist); registered_fb[i] = fb_info; @@ -1679,6 +1684,8 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) if (ret) return -EINVAL; + pm_vt_switch_unregister(fb_info->dev); + unlink_framebuffer(fb_info); if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) diff --git a/include/linux/fb.h b/include/linux/fb.h index 58b98606ac26..d49c60f5aa4c 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -501,6 +501,8 @@ struct fb_info { resource_size_t size; } ranges[0]; } *apertures; + + bool skip_vt_switch; /* no VT switch on suspend/resume required */ }; static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { -- cgit v1.2.3 From 11e17a0873aba66b251e77ff246590b9390cdc68 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 19 Feb 2013 13:31:39 -0800 Subject: drm: add initial_config function to fb helper Rather than building a config which may or may not work, let the driver build an initial fb config. This allows the driver to use the BIOS boot configuration for example, displaying kernel messages and the initial fb console on the same outputs the BIOS lit up at boot time. If that fails, the driver can still fall back the same way as the core. Signed-off-by: Jesse Barnes Signed-off-by: Chris Wilson Cc: dri-devel@lists.freedesktop.org Acked-by: Dave Airlie Reviewed-by: Imre Deak Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_fb_helper.c | 23 +++++++++++++++-------- include/drm/drm_fb_helper.h | 4 ++++ 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 59d6b9bf204b..6764dce44e84 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -1398,7 +1398,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) struct drm_mode_set *modeset; bool *enabled; int width, height; - int i, ret; + int i; DRM_DEBUG_KMS("\n"); @@ -1419,16 +1419,23 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) drm_enable_connectors(fb_helper, enabled); - ret = drm_target_cloned(fb_helper, modes, enabled, width, height); - if (!ret) { - ret = drm_target_preferred(fb_helper, modes, enabled, width, height); - if (!ret) + if (!(fb_helper->funcs->initial_config && + fb_helper->funcs->initial_config(fb_helper, crtcs, modes, + enabled, width, height))) { + memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0])); + memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0])); + + if (!drm_target_cloned(fb_helper, + modes, enabled, width, height) && + !drm_target_preferred(fb_helper, + modes, enabled, width, height)) DRM_ERROR("Unable to find initial modes\n"); - } - DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); + DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", + width, height); - drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); + drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height); + } /* need to set the modesets up here for use later */ /* fill out the connector<->crtc mappings into the modesets */ diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index c09511625a11..f97a8ef1d728 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -68,6 +68,10 @@ struct drm_fb_helper_funcs { int (*fb_probe)(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes); + bool (*initial_config)(struct drm_fb_helper *fb_helper, + struct drm_fb_helper_crtc **crtcs, + struct drm_display_mode **modes, + bool *enabled, int width, int height); }; struct drm_fb_helper_connector { -- cgit v1.2.3 From 2db76d7c3c6db93058f983c8240f7c7c25e87ee6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 26 Mar 2013 15:14:18 +0200 Subject: lib/scatterlist: sg_page_iter: support sg lists w/o backing pages The i915 driver uses sg lists for memory without backing 'struct page' pages, similarly to other IO memory regions, setting only the DMA address for these. It does this, so that it can program the HW MMU tables in a uniform way both for sg lists with and without backing pages. Without a valid page pointer we can't call nth_page to get the current page in __sg_page_iter_next, so add a helper that relevant users can call separately. Also add a helper to get the DMA address of the current page (idea from Daniel). Convert all places in i915, to use the new API. Signed-off-by: Imre Deak Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_cache.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 8 ++++---- drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++---- drivers/gpu/drm/i915/i915_gem_tiling.c | 4 ++-- include/linux/scatterlist.h | 28 +++++++++++++++++++++++----- lib/scatterlist.c | 4 +--- 8 files changed, 35 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index bc8edbeca3fd..bb8f58012189 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -109,7 +109,7 @@ drm_clflush_sg(struct sg_table *st) mb(); for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) - drm_clflush_page(sg_iter.page); + drm_clflush_page(sg_page_iter_page(&sg_iter)); mb(); return; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1d091ea12fad..f69538508d8c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1543,7 +1543,7 @@ static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object * struct sg_page_iter sg_iter; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, n) - return sg_iter.page; + return sg_page_iter_page(&sg_iter); return NULL; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a1123a32dc27..911bd40ef513 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -442,7 +442,7 @@ i915_gem_shmem_pread(struct drm_device *dev, for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, offset >> PAGE_SHIFT) { - struct page *page = sg_iter.page; + struct page *page = sg_page_iter_page(&sg_iter); if (remain <= 0) break; @@ -765,7 +765,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, offset >> PAGE_SHIFT) { - struct page *page = sg_iter.page; + struct page *page = sg_page_iter_page(&sg_iter); int partial_cacheline_write; if (remain <= 0) @@ -1647,7 +1647,7 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) obj->dirty = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { - struct page *page = sg_iter.page; + struct page *page = sg_page_iter_page(&sg_iter); if (obj->dirty) set_page_dirty(page); @@ -1827,7 +1827,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) err_pages: sg_mark_end(sg); for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) - page_cache_release(sg_iter.page); + page_cache_release(sg_page_iter_page(&sg_iter)); sg_free_table(st); kfree(st); return PTR_ERR(page); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 898615d2d5e2..c6dfc1466e3a 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -130,7 +130,7 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) i = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0); - pages[i++] = sg_iter.page; + pages[i++] = sg_page_iter_page(&sg_iter); obj->dma_buf_vmapping = vmap(pages, i, 0, PAGE_KERNEL); drm_free_large(pages); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4cbae7bbb833..24a23b31b55f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -123,8 +123,7 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt, for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { dma_addr_t page_addr; - page_addr = sg_dma_address(sg_iter.sg) + - (sg_iter.sg_pgoffset << PAGE_SHIFT); + page_addr = sg_page_iter_dma_address(&sg_iter); pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr, cache_level); if (++act_pte == I915_PPGTT_PT_ENTRIES) { @@ -424,8 +423,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev, dma_addr_t addr; for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { - addr = sg_dma_address(sg_iter.sg) + - (sg_iter.sg_pgoffset << PAGE_SHIFT); + addr = sg_page_iter_dma_address(&sg_iter); iowrite32(gen6_pte_encode(dev, addr, level), >t_entries[i]); i++; } diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index f799708bcb85..c807eb93755b 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -481,7 +481,7 @@ i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) i = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { - struct page *page = sg_iter.page; + struct page *page = sg_page_iter_page(&sg_iter); char new_bit_17 = page_to_phys(page) >> 17; if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) { @@ -511,7 +511,7 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) i = 0; for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { - if (page_to_phys(sg_iter.page) & (1 << 17)) + if (page_to_phys(sg_page_iter_page(&sg_iter)) & (1 << 17)) __set_bit(i, obj->bit_17); else __clear_bit(i, obj->bit_17); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 2d8bdaef9611..e96b9546c4c6 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -235,13 +235,13 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, * sg page iterator * * Iterates over sg entries page-by-page. On each successful iteration, - * @piter->page points to the current page, @piter->sg to the sg holding this - * page and @piter->sg_pgoffset to the page's page offset within the sg. The - * iteration will stop either when a maximum number of sg entries was reached - * or a terminating sg (sg_last(sg) == true) was reached. + * you can call sg_page_iter_page(@piter) and sg_page_iter_dma_address(@piter) + * to get the current page and its dma address. @piter->sg will point to the + * sg holding this page and @piter->sg_pgoffset to the page's page offset + * within the sg. The iteration will stop either when a maximum number of sg + * entries was reached or a terminating sg (sg_last(sg) == true) was reached. */ struct sg_page_iter { - struct page *page; /* current page */ struct scatterlist *sg; /* sg holding the page */ unsigned int sg_pgoffset; /* page offset within the sg */ @@ -255,6 +255,24 @@ bool __sg_page_iter_next(struct sg_page_iter *piter); void __sg_page_iter_start(struct sg_page_iter *piter, struct scatterlist *sglist, unsigned int nents, unsigned long pgoffset); +/** + * sg_page_iter_page - get the current page held by the page iterator + * @piter: page iterator holding the page + */ +static inline struct page *sg_page_iter_page(struct sg_page_iter *piter) +{ + return nth_page(sg_page(piter->sg), piter->sg_pgoffset); +} + +/** + * sg_page_iter_dma_address - get the dma address of the current page held by + * the page iterator. + * @piter: page iterator holding the page + */ +static inline dma_addr_t sg_page_iter_dma_address(struct sg_page_iter *piter) +{ + return sg_dma_address(piter->sg) + (piter->sg_pgoffset << PAGE_SHIFT); +} /** * for_each_sg_page - iterate over the pages of the given sg list diff --git a/lib/scatterlist.c b/lib/scatterlist.c index b83c144d731f..a1cf8cae60e7 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -401,7 +401,6 @@ void __sg_page_iter_start(struct sg_page_iter *piter, piter->__pg_advance = 0; piter->__nents = nents; - piter->page = NULL; piter->sg = sglist; piter->sg_pgoffset = pgoffset; } @@ -426,7 +425,6 @@ bool __sg_page_iter_next(struct sg_page_iter *piter) if (!--piter->__nents || !piter->sg) return false; } - piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset); return true; } @@ -496,7 +494,7 @@ bool sg_miter_next(struct sg_mapping_iter *miter) miter->__remaining = min_t(unsigned long, miter->__remaining, PAGE_SIZE - miter->__offset); } - miter->page = miter->piter.page; + miter->page = sg_page_iter_page(&miter->piter); miter->consumed = miter->length = miter->__remaining; if (miter->__flags & SG_MITER_ATOMIC) -- cgit v1.2.3 From a0d8dde9cbde712fad65822152d2721eec1ca656 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Tue, 12 Feb 2013 16:46:46 +0530 Subject: OMAPDSS: panels: keep platform data of all panels in a single header Structs for platform data of omapdss panels are found in headers in the 'include/video/' path. Board files populate these structs with platform specific values, and the panel driver uses these to configure the panel. Currently, each panel has it's own header in the above path. Move all the omapdss panel platform data structs to a single header omap-panel-data.h. This is useful because: - All other omapdss panel drivers will be modified to use platform data. This would lead to a lot of panel headers usable only by omapdss. A lot of these platform data structs are trivial, and don't really need a separate header. - Platform data would be eventually removed, and platform information would be passed via device tree. Therefore, omapdss panel platform data structs are temporary, and will be easier to remove if they are all in the same header. - All board files will have to include the same header to configure a panel's platform data, that makes the board files more consistent. Signed-off-by: Archit Taneja --- arch/arm/mach-omap2/board-2430sdp.c | 2 +- arch/arm/mach-omap2/board-3430sdp.c | 2 +- arch/arm/mach-omap2/board-am3517evm.c | 3 +- arch/arm/mach-omap2/board-cm-t35.c | 3 +- arch/arm/mach-omap2/board-devkit8000.c | 3 +- arch/arm/mach-omap2/board-h4.c | 2 +- arch/arm/mach-omap2/board-igep0020.c | 2 +- arch/arm/mach-omap2/board-ldp.c | 2 +- arch/arm/mach-omap2/board-omap3beagle.c | 2 +- arch/arm/mach-omap2/board-omap3evm.c | 2 +- arch/arm/mach-omap2/board-omap3stalker.c | 3 +- arch/arm/mach-omap2/board-overo.c | 3 +- arch/arm/mach-omap2/dss-common.c | 4 +- drivers/video/omap2/displays/panel-generic-dpi.c | 2 +- drivers/video/omap2/displays/panel-n8x0.c | 2 +- drivers/video/omap2/displays/panel-picodlp.c | 2 +- drivers/video/omap2/displays/panel-taal.c | 2 +- drivers/video/omap2/displays/panel-tfp410.c | 2 +- include/video/omap-panel-data.h | 103 +++++++++++++++++++++++ include/video/omap-panel-generic-dpi.h | 37 -------- include/video/omap-panel-n8x0.h | 15 ---- include/video/omap-panel-nokia-dsi.h | 32 ------- include/video/omap-panel-picodlp.h | 23 ----- include/video/omap-panel-tfp410.h | 35 -------- 24 files changed, 121 insertions(+), 167 deletions(-) create mode 100644 include/video/omap-panel-data.h delete mode 100644 include/video/omap-panel-generic-dpi.h delete mode 100644 include/video/omap-panel-n8x0.h delete mode 100644 include/video/omap-panel-nokia-dsi.h delete mode 100644 include/video/omap-panel-picodlp.h delete mode 100644 include/video/omap-panel-tfp410.h (limited to 'include') diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index a3e0aaa4886b..1322ed707b30 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -38,7 +38,7 @@ #include "gpmc-smc91x.h" #include