summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Chauvet <kwizart@gmail.com>2014-05-22 18:48:59 +0200
committerNicolas Chauvet <kwizart@gmail.com>2014-05-22 18:48:59 +0200
commitbc83297fd5cb14ff1f07c79868f50665dde26396 (patch)
tree14b6592cfda603c4dd5a56a9ac17d69dd0a4f8fe
parentf64d494576a3f78a4a76923ce283a208f39251d6 (diff)
downloadkernel-bc83297fd5cb14ff1f07c79868f50665dde26396.tar.gz
kernel-bc83297fd5cb14ff1f07c79868f50665dde26396.tar.xz
kernel-bc83297fd5cb14ff1f07c79868f50665dde26396.zip
Add HDMI 5v patches
-rw-r--r--0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch141
-rw-r--r--0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch251
-rw-r--r--0003-To-implement-hotplug-detection-in-a-race-free-manner.patch374
-rw-r--r--0004-Rework-Tagr-patch4.patch159
-rw-r--r--0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch50
-rw-r--r--kernel.spec11
6 files changed, 986 insertions, 0 deletions
diff --git a/0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch b/0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch
new file mode 100644
index 00000000..c43fa9fd
--- /dev/null
+++ b/0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch
@@ -0,0 +1,141 @@
+From c561057e64400d0c125116ea4c431a8139df279d Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Thu, 22 May 2014 17:56:39 +0200
+Subject: [PATCH 1/5] Some drivers need to be able to have a perfect race-free fbcon setup.
+ Current drivers only enable hotplug processing after the call to
+ drm_fb_helper_initial_config which leaves a tiny but important race.
+
+This race is especially noticable on embedded platforms where the
+driver itself enables the voltage for the hdmi output, since only then
+will monitors (after a bit of delay, as usual) respond by asserting
+the hpd pin.
+
+Most of the infrastructure is already there with the split-out
+drm_fb_helper_init. And drm_fb_helper_initial_config already has all
+the required locking to handle concurrent hpd events since
+
+commit 53f1904bced78d7c00f5d874c662ec3ac85d0f9f
+Author: Daniel Vetter <daniel.vetter at ffwll.ch>
+Date: Thu Mar 20 14:26:35 2014 +0100
+
+ drm/fb-helper: improve drm_fb_helper_initial_config locking
+
+The only missing bit is making drm_fb_helper_hotplug_event save
+against concurrent calls of drm_fb_helper_initial_config. The only
+unprotected bit is the check for fb_helper->fb.
+
+With that drivers can first initialize the fb helper, then enabel
+hotplug processing and then set up the initial config all in a
+completely race-free manner. Update kerneldoc and convert i915 as a
+proof of concept.
+
+Feature requested by Thierry since his tegra driver atm reliably boots
+slowly enough to misses the hotplug event for an external hdmi screen,
+but also reliably boots to quickly for the hpd pin to be asserted when
+the fb helper calls into the hdmi ->detect function.
+
+Cc: Thierry Reding <treding at nvidia.com>
+Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
+Signed-off-by: Thierry Reding <treding at nvidia.com>
+---
+ drivers/gpu/drm/drm_fb_helper.c | 11 +++++------
+ drivers/gpu/drm/i915/i915_dma.c | 3 ---
+ drivers/gpu/drm/i915/i915_drv.c | 2 --
+ drivers/gpu/drm/i915/i915_drv.h | 1 -
+ drivers/gpu/drm/i915/i915_irq.c | 4 ----
+ 5 files changed, 5 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
+index e95ed58..80ce92a 100644
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -1587,8 +1587,10 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
+ * either the output polling work or a work item launched from the driver's
+ * hotplug interrupt).
+ *
+- * Note that the driver must ensure that this is only called _after_ the fb has
+- * been fully set up, i.e. after the call to drm_fb_helper_initial_config.
++ * Note that drivers may call this even before calling
++ * drm_fb_helper_initial_config but only aftert drm_fb_helper_init. This allows
++ * for a race-free fbcon setup and will make sure that the fbdev emulation will
++ * not miss any hotplug events.
+ *
+ * RETURNS:
+ * 0 on success and a non-zero error code otherwise.
+@@ -1598,11 +1600,8 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
+ struct drm_device *dev = fb_helper->dev;
+ u32 max_width, max_height;
+
+- if (!fb_helper->fb)
+- return 0;
+-
+ mutex_lock(&fb_helper->dev->mode_config.mutex);
+- if (!drm_fb_helper_is_bound(fb_helper)) {
++ if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
+ fb_helper->delayed_hotplug = true;
+ mutex_unlock(&fb_helper->dev->mode_config.mutex);
+ return 0;
+diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
+index f14c47a..31b6733 100644
+--- a/drivers/gpu/drm/i915/i915_dma.c
++++ b/drivers/gpu/drm/i915/i915_dma.c
+@@ -1372,9 +1372,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
+ */
+ intel_fbdev_initial_config(dev);
+
+- /* Only enable hotplug handling once the fbdev is fully set up. */
+- dev_priv->enable_hotplug_processing = true;
+-
+ drm_kms_helper_poll_init(dev);
+
+ return 0;
+diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
+index 009d677..50ae1d9 100644
+--- a/drivers/gpu/drm/i915/i915_drv.c
++++ b/drivers/gpu/drm/i915/i915_drv.c
+@@ -526,7 +526,6 @@ static int i915_drm_freeze(struct drm_device *dev)
+ cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
+
+ drm_irq_uninstall(dev);
+- dev_priv->enable_hotplug_processing = false;
+ /*
+ * Disable CRTCs directly since we want to preserve sw state
+ * for _thaw.
+@@ -668,7 +667,6 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
+ * notifications.
+ * */
+ intel_hpd_init(dev);
+- dev_priv->enable_hotplug_processing = true;
+ /* Config may have changed between suspend and resume */
+ intel_resume_hotplug(dev);
+ }
+diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
+index 3656e0d..002600f 100644
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -1396,7 +1396,6 @@ struct drm_i915_private {
+ u32 pipestat_irq_mask[I915_MAX_PIPES];
+
+ struct work_struct hotplug_work;
+- bool enable_hotplug_processing;
+ struct {
+ unsigned long hpd_last_jiffies;
+ int hpd_cnt;
+diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
+index 236ca3f..698f12c 100644
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -1021,10 +1021,6 @@ static void i915_hotplug_work_func(struct work_struct *work)
+ bool changed = false;
+ u32 hpd_event_bits;
+
+- /* HPD irq before everything is fully set up. */
+- if (!dev_priv->enable_hotplug_processing)
+- return;
+-
+ mutex_lock(&mode_config->mutex);
+ DRM_DEBUG_KMS("running encoder hotplug functions\n");
+
+--
+1.7.2.1
+
diff --git a/0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch b/0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch
new file mode 100644
index 00000000..ad365c42
--- /dev/null
+++ b/0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch
@@ -0,0 +1,251 @@
+From a706d888682b95d9d711936414a175defc318632 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding at nvidia.com>
+Date: Thu, 22 May 2014 17:56:42 +0200
+Subject: [PATCH 2/5] There's no need for this to be modifiable. Make it const so that it can
+ be put into the .rodata section.
+
+Signed-off-by: Thierry Reding <treding at nvidia.com>
+---
+ drivers/gpu/drm/armada/armada_fbdev.c | 2 +-
+ drivers/gpu/drm/ast/ast_fb.c | 2 +-
+ drivers/gpu/drm/bochs/bochs_fbdev.c | 2 +-
+ drivers/gpu/drm/cirrus/cirrus_fbdev.c | 2 +-
+ drivers/gpu/drm/drm_fb_cma_helper.c | 2 +-
+ drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 2 +-
+ drivers/gpu/drm/gma500/framebuffer.c | 2 +-
+ drivers/gpu/drm/i915/intel_fbdev.c | 2 +-
+ drivers/gpu/drm/mgag200/mgag200_fb.c | 2 +-
+ drivers/gpu/drm/msm/msm_fbdev.c | 2 +-
+ drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +-
+ drivers/gpu/drm/omapdrm/omap_fbdev.c | 2 +-
+ drivers/gpu/drm/qxl/qxl_fb.c | 2 +-
+ drivers/gpu/drm/radeon/radeon_fb.c | 2 +-
+ drivers/gpu/drm/tegra/fb.c | 2 +-
+ drivers/gpu/drm/udl/udl_fb.c | 2 +-
+ include/drm/drm_fb_helper.h | 2 +-
+ 17 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
+index 948cb14..21aa126 100644
+--- a/drivers/gpu/drm/armada/armada_fbdev.c
++++ b/drivers/gpu/drm/armada/armada_fbdev.c
+@@ -131,7 +131,7 @@ static int armada_fb_probe(struct drm_fb_helper *fbh,
+ return ret;
+ }
+
+-static struct drm_fb_helper_funcs armada_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs armada_fb_helper_funcs = {
+ .gamma_set = armada_drm_crtc_gamma_set,
+ .gamma_get = armada_drm_crtc_gamma_get,
+ .fb_probe = armada_fb_probe,
+diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
+index a28640f..2113894 100644
+--- a/drivers/gpu/drm/ast/ast_fb.c
++++ b/drivers/gpu/drm/ast/ast_fb.c
+@@ -287,7 +287,7 @@ static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ *blue = ast_crtc->lut_b[regno] << 8;
+ }
+
+-static struct drm_fb_helper_funcs ast_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
+ .gamma_set = ast_fb_gamma_set,
+ .gamma_get = ast_fb_gamma_get,
+ .fb_probe = astfb_create,
+diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
+index 561b844..17e5c17 100644
+--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
++++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
+@@ -179,7 +179,7 @@ void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+ *blue = regno;
+ }
+
+-static struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
+ .gamma_set = bochs_fb_gamma_set,
+ .gamma_get = bochs_fb_gamma_get,
+ .fb_probe = bochsfb_create,
+diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+index 32bbba0..2bd0291 100644
+--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
++++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+@@ -288,7 +288,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev,
+ return 0;
+ }
+
+-static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
+ .gamma_set = cirrus_crtc_fb_gamma_set,
+ .gamma_get = cirrus_crtc_fb_gamma_get,
+ .fb_probe = cirrusfb_create,
+diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
+index 61b5a47..b74f9e5 100644
+--- a/drivers/gpu/drm/drm_fb_cma_helper.c
++++ b/drivers/gpu/drm/drm_fb_cma_helper.c
+@@ -327,7 +327,7 @@ err_drm_gem_cma_free_object:
+ return ret;
+ }
+
+-static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
++static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+ .fb_probe = drm_fbdev_cma_create,
+ };
+
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+index addbf75..7ccf049 100644
+--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+@@ -233,7 +233,7 @@ out:
+ return ret;
+ }
+
+-static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = {
+ .fb_probe = exynos_drm_fbdev_create,
+ };
+
+diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
+index e7fcc14..76e4d77 100644
+--- a/drivers/gpu/drm/gma500/framebuffer.c
++++ b/drivers/gpu/drm/gma500/framebuffer.c
+@@ -561,7 +561,7 @@ static int psbfb_probe(struct drm_fb_helper *helper,
+ return psbfb_create(psb_fbdev, sizes);
+ }
+
+-static struct drm_fb_helper_funcs psb_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+ .gamma_set = psbfb_gamma_set,
+ .gamma_get = psbfb_gamma_get,
+ .fb_probe = psbfb_probe,
+diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
+index f6f26a3..f5773ea 100644
+--- a/drivers/gpu/drm/i915/intel_fbdev.c
++++ b/drivers/gpu/drm/i915/intel_fbdev.c
+@@ -452,7 +452,7 @@ out:
+ return true;
+ }
+
+-static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+ .initial_config = intel_fb_initial_config,
+ .gamma_set = intel_crtc_fb_gamma_set,
+ .gamma_get = intel_crtc_fb_gamma_get,
+diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
+index 13b7dd8..a4319ab 100644
+--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
++++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
+@@ -272,7 +272,7 @@ static int mga_fbdev_destroy(struct drm_device *dev,
+ return 0;
+ }
+
+-static struct drm_fb_helper_funcs mga_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs mga_fb_helper_funcs = {
+ .gamma_set = mga_crtc_fb_gamma_set,
+ .gamma_get = mga_crtc_fb_gamma_get,
+ .fb_probe = mgag200fb_create,
+diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
+index a752ab8..c229bf6 100644
+--- a/drivers/gpu/drm/msm/msm_fbdev.c
++++ b/drivers/gpu/drm/msm/msm_fbdev.c
+@@ -177,7 +177,7 @@ static void msm_crtc_fb_gamma_get(struct drm_crtc *crtc,
+ DBG("fbdev: get gamma");
+ }
+
+-static struct drm_fb_helper_funcs msm_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs msm_fb_helper_funcs = {
+ .gamma_set = msm_crtc_fb_gamma_set,
+ .gamma_get = msm_crtc_fb_gamma_get,
+ .fb_probe = msm_fbdev_create,
+diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+index 64a42cf..8e9c07b 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+@@ -438,7 +438,7 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info)
+ info->flags |= FBINFO_HWACCEL_DISABLED;
+ }
+
+-static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
++static const struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
+ .gamma_set = nouveau_fbcon_gamma_set,
+ .gamma_get = nouveau_fbcon_gamma_get,
+ .fb_probe = nouveau_fbcon_create,
+diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+index 1388ca7..4cb1208 100644
+--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+@@ -281,7 +281,7 @@ fail:
+ return ret;
+ }
+
+-static struct drm_fb_helper_funcs omap_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs omap_fb_helper_funcs = {
+ .fb_probe = omap_fbdev_create,
+ };
+
+diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
+index f437b30..cf89614 100644
+--- a/drivers/gpu/drm/qxl/qxl_fb.c
++++ b/drivers/gpu/drm/qxl/qxl_fb.c
+@@ -660,7 +660,7 @@ static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
+ return 0;
+ }
+
+-static struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
+ .fb_probe = qxl_fb_find_or_create_single,
+ };
+
+diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
+index 665ced3..ad97afd 100644
+--- a/drivers/gpu/drm/radeon/radeon_fb.c
++++ b/drivers/gpu/drm/radeon/radeon_fb.c
+@@ -331,7 +331,7 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
+ return 0;
+ }
+
+-static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
+ .gamma_set = radeon_crtc_fb_gamma_set,
+ .gamma_get = radeon_crtc_fb_gamma_get,
+ .fb_probe = radeonfb_create,
+diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
+index f7fca09..75bed72 100644
+--- a/drivers/gpu/drm/tegra/fb.c
++++ b/drivers/gpu/drm/tegra/fb.c
+@@ -267,7 +267,7 @@ release:
+ return err;
+ }
+
+-static struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+ .fb_probe = tegra_fbdev_probe,
+ };
+
+diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
+index 3771763..0647c8c 100644
+--- a/drivers/gpu/drm/udl/udl_fb.c
++++ b/drivers/gpu/drm/udl/udl_fb.c
+@@ -550,7 +550,7 @@ out:
+ return ret;
+ }
+
+-static struct drm_fb_helper_funcs udl_fb_helper_funcs = {
++static const struct drm_fb_helper_funcs udl_fb_helper_funcs = {
+ .fb_probe = udlfb_create,
+ };
+
+diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
+index 6e622f7..e8c8eeb 100644
+--- a/include/drm/drm_fb_helper.h
++++ b/include/drm/drm_fb_helper.h
+@@ -87,7 +87,7 @@ struct drm_fb_helper {
+ struct drm_fb_helper_crtc *crtc_info;
+ int connector_count;
+ struct drm_fb_helper_connector **connector_info;
+- struct drm_fb_helper_funcs *funcs;
++ const struct drm_fb_helper_funcs *funcs;
+ struct fb_info *fbdev;
+ u32 pseudo_palette[17];
+ struct list_head kernel_fb_list;
+--
+1.7.2.1
+
diff --git a/0003-To-implement-hotplug-detection-in-a-race-free-manner.patch b/0003-To-implement-hotplug-detection-in-a-race-free-manner.patch
new file mode 100644
index 00000000..ec466db6
--- /dev/null
+++ b/0003-To-implement-hotplug-detection-in-a-race-free-manner.patch
@@ -0,0 +1,374 @@
+From 8ba743aba5ff865cb7913c9e85b02ac1a3e4c587 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <treding at nvidia.com>
+Date: Thu, 22 May 2014 17:56:45 +0200
+Subject: [PATCH 3/5] To implement hotplug detection in a race-free manner, drivers must call
+ drm_kms_helper_poll_init() before hotplug events can be triggered. Such
+ events can be triggered right after any of the encoders or connectors
+ are initialized. At the same time, if the drm_fb_helper_hotplug_event()
+ helper is used by a driver, then the poll helper requires some parts of
+ the FB helper to be initialized to prevent a crash.
+
+At the same time, drm_fb_helper_init() requires information that is not
+necessarily available at such an early stage (number of CRTCs and
+connectors), so it cannot be used yet.
+
+Add a new helper, drm_fb_helper_prepare(), that initializes the bare
+minimum needed to allow drm_kms_helper_poll_init() to execute and any
+subsequent hotplug events to be processed properly.
+
+Signed-off-by: Thierry Reding <treding at nvidia.com>
+---
+ drivers/gpu/drm/armada/armada_fbdev.c | 2 +-
+ drivers/gpu/drm/ast/ast_fb.c | 4 ++-
+ drivers/gpu/drm/bochs/bochs_fbdev.c | 3 +-
+ drivers/gpu/drm/cirrus/cirrus_fbdev.c | 4 ++-
+ drivers/gpu/drm/drm_fb_cma_helper.c | 3 +-
+ drivers/gpu/drm/drm_fb_helper.c | 43 ++++++++++++++++++++++-------
+ drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 3 +-
+ drivers/gpu/drm/gma500/framebuffer.c | 3 +-
+ drivers/gpu/drm/i915/intel_fbdev.c | 3 +-
+ drivers/gpu/drm/mgag200/mgag200_fb.c | 3 +-
+ drivers/gpu/drm/msm/msm_fbdev.c | 2 +-
+ drivers/gpu/drm/nouveau/nouveau_fbcon.c | 3 +-
+ drivers/gpu/drm/omapdrm/omap_fbdev.c | 2 +-
+ drivers/gpu/drm/qxl/qxl_fb.c | 5 +++-
+ drivers/gpu/drm/radeon/radeon_fb.c | 4 ++-
+ drivers/gpu/drm/tegra/fb.c | 4 +--
+ drivers/gpu/drm/udl/udl_fb.c | 3 +-
+ include/drm/drm_fb_helper.h | 2 +
+ 18 files changed, 68 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
+index 21aa126..9437e11 100644
+--- a/drivers/gpu/drm/armada/armada_fbdev.c
++++ b/drivers/gpu/drm/armada/armada_fbdev.c
+@@ -149,7 +149,7 @@ int armada_fbdev_init(struct drm_device *dev)
+
+ priv->fbdev = fbh;
+
+- fbh->funcs = &armada_fb_helper_funcs;
++ drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, fbh, 1, 1);
+ if (ret) {
+diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c
+index 2113894..cba45c7 100644
+--- a/drivers/gpu/drm/ast/ast_fb.c
++++ b/drivers/gpu/drm/ast/ast_fb.c
+@@ -328,8 +328,10 @@ int ast_fbdev_init(struct drm_device *dev)
+ return -ENOMEM;
+
+ ast->fbdev = afbdev;
+- afbdev->helper.funcs = &ast_fb_helper_funcs;
+ spin_lock_init(&afbdev->dirty_lock);
++
++ drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
++
+ ret = drm_fb_helper_init(dev, &afbdev->helper,
+ 1, 1);
+ if (ret) {
+diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c
+index 17e5c17..19cf3e9 100644
+--- a/drivers/gpu/drm/bochs/bochs_fbdev.c
++++ b/drivers/gpu/drm/bochs/bochs_fbdev.c
+@@ -189,7 +189,8 @@ int bochs_fbdev_init(struct bochs_device *bochs)
+ {
+ int ret;
+
+- bochs->fb.helper.funcs = &bochs_fb_helper_funcs;
++ drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
++ &bochs_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
+ 1, 1);
+diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+index 2bd0291..2a135f2 100644
+--- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c
++++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
+@@ -306,9 +306,11 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
+ return -ENOMEM;
+
+ cdev->mode_info.gfbdev = gfbdev;
+- gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
+ spin_lock_init(&gfbdev->dirty_lock);
+
++ drm_fb_helper_prepare(cdev->dev, &gfbdev->helper,
++ &cirrus_fb_helper_funcs);
++
+ ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
+ cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
+ if (ret) {
+diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
+index b74f9e5..acbbd23 100644
+--- a/drivers/gpu/drm/drm_fb_cma_helper.c
++++ b/drivers/gpu/drm/drm_fb_cma_helper.c
+@@ -354,9 +354,10 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+ return ERR_PTR(-ENOMEM);
+ }
+
+- fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
+ helper = &fbdev_cma->fb_helper;
+
++ drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
++
+ ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
+ if (ret < 0) {
+ dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
+diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
+index 80ce92a..7788f11 100644
+--- a/drivers/gpu/drm/drm_fb_helper.c
++++ b/drivers/gpu/drm/drm_fb_helper.c
+@@ -49,10 +49,11 @@ static LIST_HEAD(kernel_fb_helper_list);
+ * helper functions used by many drivers to implement the kernel mode setting
+ * interfaces.
+ *
+- * Initialization is done as a three-step process with drm_fb_helper_init(),
+- * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config().
+- * Drivers with fancier requirements than the default behaviour can override the
+- * second step with their own code. Teardown is done with drm_fb_helper_fini().
++ * Initialization is done as a four-step process with drm_fb_helper_prepare(),
++ * drm_fb_helper_init(), drm_fb_helper_single_add_all_connectors() and
++ * drm_fb_helper_initial_config(). Drivers with fancier requirements than the
++ * default behaviour can override the second step with their own code.
++ * Teardown is done with drm_fb_helper_fini().
+ *
+ * At runtime drivers should restore the fbdev console by calling
+ * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They
+@@ -502,6 +503,33 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
+ }
+
+ /**
++ * drm_fb_helper_prepare - setup a drm_fb_helper structure
++ * @dev: DRM device
++ * @helper: driver-allocated fbdev helper structure to set up
++ * @funcs: pointer to structure of functions associate with this helper
++ *
++ * Sets up the bare minimum to make the framebuffer helper usable. This is
++ * useful to implement race-free initialization of the polling helpers. In
++ * that case a typical sequence would be:
++ *
++ * - call drm_fb_helper_prepare()
++ * - set dev->mode_config.funcs
++ * - perform driver-specific setup
++ * - call drm_kms_helper_poll_init()
++ * - call drm_fb_helper_init()
++ * - call drm_fb_helper_single_add_all_connectors()
++ * - call drm_fb_helper_initial_config()
++ */
++void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
++ const struct drm_fb_helper_funcs *funcs)
++{
++ INIT_LIST_HEAD(&helper->kernel_fb_list);
++ helper->funcs = funcs;
++ helper->dev = dev;
++}
++EXPORT_SYMBOL(drm_fb_helper_prepare);
++
++/**
+ * drm_fb_helper_init - initialize a drm_fb_helper structure
+ * @dev: drm device
+ * @fb_helper: driver-allocated fbdev helper structure to initialize
+@@ -513,8 +541,7 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
+ * nor register the fbdev. This is only done in drm_fb_helper_initial_config()
+ * to allow driver writes more control over the exact init sequence.
+ *
+- * Drivers must set fb_helper->funcs before calling
+- * drm_fb_helper_initial_config().
++ * Drivers must call drm_fb_helper_prepare() before calling this function.
+ *
+ * RETURNS:
+ * Zero if everything went ok, nonzero otherwise.
+@@ -529,10 +556,6 @@ int drm_fb_helper_init(struct drm_device *dev,
+ if (!max_conn_count)
+ return -EINVAL;
+
+- fb_helper->dev = dev;
+-
+- INIT_LIST_HEAD(&fb_helper->kernel_fb_list);
+-
+ fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
+ if (!fb_helper->crtc_info)
+ return -ENOMEM;
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+index 7ccf049..4644397 100644
+--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+@@ -274,7 +274,8 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
+ return -ENOMEM;
+
+ private->fb_helper = helper = &fbdev->drm_fb_helper;
+- helper->funcs = &exynos_drm_fb_helper_funcs;
++
++ drm_fb_helper_prepare(dev, helper, &exynos_drm_fb_helper_funcs);
+
+ num_crtc = dev->mode_config.num_crtc;
+
+diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
+index 76e4d77..d0dd3be 100644
+--- a/drivers/gpu/drm/gma500/framebuffer.c
++++ b/drivers/gpu/drm/gma500/framebuffer.c
+@@ -600,7 +600,8 @@ int psb_fbdev_init(struct drm_device *dev)
+ }
+
+ dev_priv->fbdev = fbdev;
+- fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
++
++ drm_fb_helper_prepare(dev, &fbdev->psb_fb_helper, &psb_fb_helper_funcs);
+
+ drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
+ INTELFB_CONN_LIMIT);
+diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
+index f5773ea..c5b1394 100644
+--- a/drivers/gpu/drm/i915/intel_fbdev.c
++++ b/drivers/gpu/drm/i915/intel_fbdev.c
+@@ -623,7 +623,8 @@ int intel_fbdev_init(struct drm_device *dev)
+ if (ifbdev == NULL)
+ return -ENOMEM;
+
+- ifbdev->helper.funcs = &intel_fb_helper_funcs;
++ drm_fb_helper_probe(dev, &ifbdev->helper, &intel_fb_helper_funcs);
++
+ if (!intel_fbdev_init_bios(dev, ifbdev))
+ ifbdev->preferred_bpp = 32;
+
+diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
+index a4319ab..5451dc5 100644
+--- a/drivers/gpu/drm/mgag200/mgag200_fb.c
++++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
+@@ -293,9 +293,10 @@ int mgag200_fbdev_init(struct mga_device *mdev)
+ return -ENOMEM;
+
+ mdev->mfbdev = mfbdev;
+- mfbdev->helper.funcs = &mga_fb_helper_funcs;
+ spin_lock_init(&mfbdev->dirty_lock);
+
++ drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs);
++
+ ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
+ mdev->num_crtc, MGAG200FB_CONN_LIMIT);
+ if (ret)
+diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
+index c229bf6..c7d6e85 100644
+--- a/drivers/gpu/drm/msm/msm_fbdev.c
++++ b/drivers/gpu/drm/msm/msm_fbdev.c
+@@ -197,7 +197,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev)
+
+ helper = &fbdev->base;
+
+- helper->funcs = &msm_fb_helper_funcs;
++ drm_fb_helper_prepare(dev, helper, &msm_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, helper,
+ priv->num_crtcs, priv->num_connectors);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+index 8e9c07b..afe706a 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
++++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+@@ -464,7 +464,8 @@ nouveau_fbcon_init(struct drm_device *dev)
+
+ fbcon->dev = dev;
+ drm->fbcon = fbcon;
+- fbcon->helper.funcs = &nouveau_fbcon_helper_funcs;
++
++ drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, &fbcon->helper,
+ dev->mode_config.num_crtc, 4);
+diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+index 4cb1208..8436c68 100644
+--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+@@ -325,7 +325,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
+
+ helper = &fbdev->base;
+
+- helper->funcs = &omap_fb_helper_funcs;
++ drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, helper,
+ priv->num_crtcs, priv->num_connectors);
+diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
+index cf89614..df56788 100644
+--- a/drivers/gpu/drm/qxl/qxl_fb.c
++++ b/drivers/gpu/drm/qxl/qxl_fb.c
+@@ -676,9 +676,12 @@ int qxl_fbdev_init(struct qxl_device *qdev)
+
+ qfbdev->qdev = qdev;
+ qdev->mode_info.qfbdev = qfbdev;
+- qfbdev->helper.funcs = &qxl_fb_helper_funcs;
+ spin_lock_init(&qfbdev->delayed_ops_lock);
+ INIT_LIST_HEAD(&qfbdev->delayed_ops);
++
++ drm_fb_helper_prepare(qdev->ddev, &qfbdev->helper,
++ &qxl_fb_helper_funcs);
++
+ ret = drm_fb_helper_init(qdev->ddev, &qfbdev->helper,
+ qxl_num_crtc /* num_crtc - QXL supports just 1 */,
+ QXLFB_CONN_LIMIT);
+diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
+index ad97afd..db598d7 100644
+--- a/drivers/gpu/drm/radeon/radeon_fb.c
++++ b/drivers/gpu/drm/radeon/radeon_fb.c
+@@ -353,7 +353,9 @@ int radeon_fbdev_init(struct radeon_device *rdev)
+
+ rfbdev->rdev = rdev;
+ rdev->mode_info.rfbdev = rfbdev;
+- rfbdev->helper.funcs = &radeon_fb_helper_funcs;
++
++ drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
++ &radeon_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
+ rdev->num_crtc,
+diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
+index 75bed72..2e37585 100644
+--- a/drivers/gpu/drm/tegra/fb.c
++++ b/drivers/gpu/drm/tegra/fb.c
+@@ -276,7 +276,6 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+ unsigned int num_crtc,
+ unsigned int max_connectors)
+ {
+- struct drm_fb_helper *helper;
+ struct tegra_fbdev *fbdev;
+ int err;
+
+@@ -286,8 +285,7 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+ return ERR_PTR(-ENOMEM);
+ }
+
+- fbdev->base.funcs = &tegra_fb_helper_funcs;
+- helper = &fbdev->base;
++ drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
+
+ err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
+ if (err < 0) {
+diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
+index 0647c8c..d1da339 100644
+--- a/drivers/gpu/drm/udl/udl_fb.c
++++ b/drivers/gpu/drm/udl/udl_fb.c
+@@ -583,7 +583,8 @@ int udl_fbdev_init(struct drm_device *dev)
+ return -ENOMEM;
+
+ udl->fbdev = ufbdev;
+- ufbdev->helper.funcs = &udl_fb_helper_funcs;
++
++ drm_fb_helper_prepare(dev, &ufbdev->helper, &udl_fb_helper_funcs);
+
+ ret = drm_fb_helper_init(dev, &ufbdev->helper,
+ 1, 1);
+diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
+index e8c8eeb..9b83c66 100644
+--- a/include/drm/drm_fb_helper.h
++++ b/include/drm/drm_fb_helper.h
+@@ -97,6 +97,8 @@ struct drm_fb_helper {
+ bool delayed_hotplug;
+ };
+
++void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
++ const struct drm_fb_helper_funcs *funcs);
+ int drm_fb_helper_init(struct drm_device *dev,
+ struct drm_fb_helper *helper, int crtc_count,
+ int max_conn);
+--
+1.7.2.1
+
diff --git a/0004-Rework-Tagr-patch4.patch b/0004-Rework-Tagr-patch4.patch
new file mode 100644
index 00000000..bb5af33b
--- /dev/null
+++ b/0004-Rework-Tagr-patch4.patch
@@ -0,0 +1,159 @@
+From 846f476e99bfb894bb3a7516ed86323485335de2 Mon Sep 17 00:00:00 2001
+From: Nicolas Chauvet <kwizart@gmail.com>
+Date: Thu, 22 May 2014 18:43:36 +0200
+Subject: [PATCH 4/5] Rework Tagr patch4
+
+---
+ drivers/gpu/drm/tegra/drm.c | 8 +++++-
+ drivers/gpu/drm/tegra/drm.h | 1 +
+ drivers/gpu/drm/tegra/fb.c | 47 +++++++++++++++++++++++++++++-------------
+ 3 files changed, 39 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
+index 09ee779..d492c2f 100644
+--- a/drivers/gpu/drm/tegra/drm.c
++++ b/drivers/gpu/drm/tegra/drm.c
+@@ -41,6 +41,12 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
+
+ drm_mode_config_init(drm);
+
++ err = tegra_drm_fb_prepare(drm);
++ if (err < 0)
++ return err;
++
++ drm_kms_helper_poll_init(drm);
++
+ err = host1x_device_init(device);
+ if (err < 0)
+ return err;
+@@ -60,8 +66,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
+ if (err < 0)
+ return err;
+
+- drm_kms_helper_poll_init(drm);
+-
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
+index 784fd5c..d100f70 100644
+--- a/drivers/gpu/drm/tegra/drm.h
++++ b/drivers/gpu/drm/tegra/drm.h
+@@ -284,6 +284,7 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
+ unsigned int index);
+ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
+ bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
++int tegra_drm_fb_prepare(struct drm_device *drm);
+ int tegra_drm_fb_init(struct drm_device *drm);
+ void tegra_drm_fb_exit(struct drm_device *drm);
+ #ifdef CONFIG_DRM_TEGRA_FBDEV
+diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
+index 2e37585..70d0e07 100644
+--- a/drivers/gpu/drm/tegra/fb.c
++++ b/drivers/gpu/drm/tegra/fb.c
+@@ -271,13 +271,9 @@ static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
+ .fb_probe = tegra_fbdev_probe,
+ };
+
+-static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+- unsigned int preferred_bpp,
+- unsigned int num_crtc,
+- unsigned int max_connectors)
++static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm)
+ {
+ struct tegra_fbdev *fbdev;
+- int err;
+
+ fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+ if (!fbdev) {
+@@ -287,10 +283,21 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+
+ drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
+
++ return fbdev;
++}
++
++static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
++ unsigned int preferred_bpp,
++ unsigned int num_crtc,
++ unsigned int max_connectors)
++{
++ struct drm_device *drm = fbdev->base.dev;
++ int err;
++
+ err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
+ if (err < 0) {
+ dev_err(drm->dev, "failed to initialize DRM FB helper\n");
+- goto free;
++ return err;
+ }
+
+ err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
+@@ -299,21 +306,17 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
+ goto fini;
+ }
+
+- drm_helper_disable_unused_functions(drm);
+-
+ err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
+ if (err < 0) {
+ dev_err(drm->dev, "failed to set initial configuration\n");
+ goto fini;
+ }
+
+- return fbdev;
++ return 0;
+
+ fini:
+ drm_fb_helper_fini(&fbdev->base);
+-free:
+- kfree(fbdev);
+- return ERR_PTR(err);
++ return err;
+ }
+
+ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
+@@ -367,7 +370,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
+ #endif
+ };
+
+-int tegra_drm_fb_init(struct drm_device *drm)
++int tegra_drm_fb_prepare(struct drm_device *drm)
+ {
+ #ifdef CONFIG_DRM_TEGRA_FBDEV
+ struct tegra_drm *tegra = drm->dev_private;
+@@ -382,8 +385,7 @@ int tegra_drm_fb_init(struct drm_device *drm)
+ drm->mode_config.funcs = &tegra_drm_mode_funcs;
+
+ #ifdef CONFIG_DRM_TEGRA_FBDEV
+- tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc,
+- drm->mode_config.num_connector);
++ tegra->fbdev = tegra_fbdev_create(drm);
+ if (IS_ERR(tegra->fbdev))
+ return PTR_ERR(tegra->fbdev);
+ #endif
+@@ -391,6 +393,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
+ return 0;
+ }
+
++int tegra_drm_fb_init(struct drm_device *drm)
++{
++#ifdef CONFIG_DRM_TEGRA_FBDEV
++ struct tegra_drm *tegra = drm->dev_private;
++ int err;
++
++ err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc,
++ drm->mode_config.num_connector);
++ if (err < 0)
++ return err;
++#endif
++
++ return 0;
++}
++
+ void tegra_drm_fb_exit(struct drm_device *drm)
+ {
+ #ifdef CONFIG_DRM_TEGRA_FBDEV
+--
+1.7.2.1
+
diff --git a/0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch b/0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch
new file mode 100644
index 00000000..75541700
--- /dev/null
+++ b/0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch
@@ -0,0 +1,50 @@
+From d6f359cf523ed8ee8f33c43e4899a8d4eb156d3a Mon Sep 17 00:00:00 2001
+From: Nicolas Chauvet <kwizart@gmail.com>
+Date: Thu, 22 May 2014 18:44:26 +0200
+Subject: [PATCH 5/5] ARM: tegra: trimslice - Add +5V HDMI supply
+
+---
+ arch/arm/boot/dts/tegra20-trimslice.dts | 13 ++++++++++++-
+ 1 files changed, 12 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
+index 216fa6d..3239a04 100644
+--- a/arch/arm/boot/dts/tegra20-trimslice.dts
++++ b/arch/arm/boot/dts/tegra20-trimslice.dts
+@@ -20,6 +20,7 @@
+ hdmi@54280000 {
+ status = "okay";
+
++ hdmi-supply = <&vdd_5v0_hdmi>;
+ vdd-supply = <&hdmi_vdd_reg>;
+ pll-supply = <&hdmi_pll_reg>;
+
+@@ -400,7 +401,6 @@
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+-
+ hdmi_vdd_reg: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+@@ -448,6 +448,17 @@
+ regulator-max-microvolt = <1050000>;
+ regulator-always-on;
+ };
++
++ vdd_5v0_hdmi: regulator@5 {
++ compatible = "regulator-fixed";
++ reg = <6>;
++ regulator-name = "VDDIO_HDMI";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpio = <&gpio TEGRA_GPIO(T, 2) GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ vin-supply = <&vdd_5v0_reg>;
++ };
+ };
+
+ sound {
+--
+1.7.2.1
+
diff --git a/kernel.spec b/kernel.spec
index d2b19015..e2f01d4b 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -711,6 +711,12 @@ Patch21206: Update-panel-simple_3.15.patch
#http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/253575.html
Patch21210: arm-tegra-reboot-rcm.patch
+Patch21220: 0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch
+Patch21221: 0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch
+Patch21222: 0003-To-implement-hotplug-detection-in-a-race-free-manner.patch
+Patch21223: 0004-Rework-Tagr-patch4.patch
+Patch21224: 0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch
+
#rhbz 754518
Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
@@ -1355,6 +1361,11 @@ ApplyPatch 0005-NOT_FOR_UPSTREAM-staging-nvec-update-TODO.patch
ApplyPatch Update-panel-simple_3.15.patch
ApplyPatch arm-tegra-reboot-rcm.patch
+ApplyPatch 0001-Some-drivers-need-to-be-able-to-have-a-perfect-race-.patch
+ApplyPatch 0002-There-s-no-need-for-this-to-be-modifiable.-Make-it-c.patch
+ApplyPatch 0003-To-implement-hotplug-detection-in-a-race-free-manner.patch
+ApplyPatch 0004-Rework-Tagr-patch4.patch
+ApplyPatch 0005-ARM-tegra-trimslice-Add-5V-HDMI-supply.patch
#