Repository navigation
Expand file tree
/
Copy pathhdmi_hotplug.patch
More file actions
173 lines (159 loc) · 6.73 KB
/
Copy pathhdmi_hotplug.patch
File metadata and controls
173 lines (159 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
diff -ruN linux-4.0.5/drivers/gpu/drm/drm_probe_helper.c linux-4.0.5.new/drivers/gpu/drm/drm_probe_helper.c
--- linux-4.0.5/drivers/gpu/drm/drm_probe_helper.c 2015-06-06 09:21:22.000000000 -0600
+++ linux-4.0.5.new/drivers/gpu/drm/drm_probe_helper.c 2015-06-13 22:35:39.759455090 -0600
@@ -295,6 +295,32 @@
}
EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
+/**
+ * drm_kms_helper_hdmi_hotplug_event - fire off KMS hotplug events
+ * @dev: drm_device whose connector state changed
+ *
+ * This function fires off the uevent for userspace and also calls the
+ * output_poll_changed function, which is most commonly used to inform the fbdev
+ * emulation code and allow it to update the fbcon output configuration.
+ *
+ * Drivers should call this from their hotplug handling code when a change is
+ * detected. Note that this function does not do any output detection of its
+ * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the
+ * driver already.
+ *
+ * This function must be called from process context with no mode
+ * setting locks held.
+ */
+void drm_kms_helper_hdmi_hotplug_event(struct drm_device *dev)
+{
+ /* send a uevent + call fbdev */
+ drm_sysfs_hdmi_hotplug_event(dev);
+ if (dev->mode_config.funcs->output_poll_changed)
+ dev->mode_config.funcs->output_poll_changed(dev);
+}
+EXPORT_SYMBOL(drm_kms_helper_hdmi_hotplug_event);
+
+
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
static void output_poll_execute(struct work_struct *work)
{
diff -ruN linux-4.0.5/drivers/gpu/drm/drm_sysfs.c linux-4.0.5.new/drivers/gpu/drm/drm_sysfs.c
--- linux-4.0.5/drivers/gpu/drm/drm_sysfs.c 2015-06-06 09:21:22.000000000 -0600
+++ linux-4.0.5.new/drivers/gpu/drm/drm_sysfs.c 2015-06-13 22:30:18.634016865 -0600
@@ -490,6 +490,26 @@
}
EXPORT_SYMBOL(drm_sysfs_hotplug_event);
+/**
+ * drm_sysfs_hdmi_hotplug_event - generate a DRM uevent
+ * @dev: DRM device
+ *
+ * Send a uevent for the DRM device specified by @dev. Currently we only
+ * set HOTPLUG=1 and HDMI=1 in the uevent environment, but this could be expanded to
+ * deal with other types of events.
+ */
+void drm_sysfs_hdmi_hotplug_event(struct drm_device *dev)
+{
+ char *event_string = "HOTPLUG=1";
+ char *hdmi_event_string = "HDMI=1";
+ char *envp[] = { event_string, hdmi_event_string, NULL };
+
+ DRM_DEBUG("generating hdmi hotplug event\n");
+
+ kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
+}
+EXPORT_SYMBOL(drm_sysfs_hdmi_hotplug_event);
+
static void drm_sysfs_release(struct device *dev)
{
kfree(dev);
diff -ruN linux-4.0.5/drivers/gpu/drm/i915/i915_drv.c linux-4.0.5.new/drivers/gpu/drm/i915/i915_drv.c
--- linux-4.0.5/drivers/gpu/drm/i915/i915_drv.c 2015-06-06 09:21:22.000000000 -0600
+++ linux-4.0.5.new/drivers/gpu/drm/i915/i915_drv.c 2015-06-11 11:17:13.066535399 -0600
@@ -525,7 +525,7 @@
spin_unlock_irq(&dev_priv->irq_lock);
cancel_work_sync(&dev_priv->dig_port_work);
- cancel_work_sync(&dev_priv->hotplug_work);
+ cancel_delayed_work_sync(&dev_priv->hotplug_work);
cancel_delayed_work_sync(&dev_priv->hotplug_reenable_work);
}
diff -ruN linux-4.0.5/drivers/gpu/drm/i915/i915_drv.h linux-4.0.5.new/drivers/gpu/drm/i915/i915_drv.h
--- linux-4.0.5/drivers/gpu/drm/i915/i915_drv.h 2015-06-06 09:21:22.000000000 -0600
+++ linux-4.0.5.new/drivers/gpu/drm/i915/i915_drv.h 2015-06-11 11:17:57.820448575 -0600
@@ -1702,7 +1702,7 @@
u32 pm_rps_events;
u32 pipestat_irq_mask[I915_MAX_PIPES];
- struct work_struct hotplug_work;
+ struct delayed_work hotplug_work;
struct {
unsigned long hpd_last_jiffies;
int hpd_cnt;
diff -ruN linux-4.0.5/drivers/gpu/drm/i915/i915_irq.c linux-4.0.5.new/drivers/gpu/drm/i915/i915_irq.c
--- linux-4.0.5/drivers/gpu/drm/i915/i915_irq.c 2015-06-06 09:21:22.000000000 -0600
+++ linux-4.0.5.new/drivers/gpu/drm/i915/i915_irq.c 2015-06-13 22:34:12.418260951 -0600
@@ -873,6 +873,8 @@
return true;
}
+#define HOTPLUG_DELAY_MS 800
+
static void i915_digport_work_func(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
@@ -917,7 +919,8 @@
spin_lock_irq(&dev_priv->irq_lock);
dev_priv->hpd_event_bits |= old_bits;
spin_unlock_irq(&dev_priv->irq_lock);
- schedule_work(&dev_priv->hotplug_work);
+ mod_delayed_work(system_wq, &dev_priv->hotplug_work,
+ msecs_to_jiffies(HOTPLUG_DELAY_MS));
}
}
@@ -929,7 +932,7 @@
static void i915_hotplug_work_func(struct work_struct *work)
{
struct drm_i915_private *dev_priv =
- container_of(work, struct drm_i915_private, hotplug_work);
+ container_of(work, struct drm_i915_private, hotplug_work.work);
struct drm_device *dev = dev_priv->dev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct intel_connector *intel_connector;
@@ -993,7 +996,7 @@
mutex_unlock(&mode_config->mutex);
if (changed)
- drm_kms_helper_hotplug_event(dev);
+ drm_kms_helper_hdmi_hotplug_event(dev);
}
static void ironlake_rps_change_irq_handler(struct drm_device *dev)
@@ -1630,7 +1633,8 @@
if (queue_dig)
queue_work(dev_priv->dp_wq, &dev_priv->dig_port_work);
if (queue_hp)
- schedule_work(&dev_priv->hotplug_work);
+ mod_delayed_work(system_wq, &dev_priv->hotplug_work,
+ msecs_to_jiffies(HOTPLUG_DELAY_MS));
}
static void gmbus_irq_handler(struct drm_device *dev)
@@ -4350,7 +4354,7 @@
{
struct drm_device *dev = dev_priv->dev;
- INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+ INIT_DELAYED_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
INIT_WORK(&dev_priv->dig_port_work, i915_digport_work_func);
INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
diff -ruN linux-4.0.5/include/drm/drm_crtc_helper.h linux-4.0.5.new/include/drm/drm_crtc_helper.h
--- linux-4.0.5/include/drm/drm_crtc_helper.h 2015-08-16 21:52:51.000000000 -0600
+++ linux-4.0.5.new/include/drm/drm_crtc_helper.h 2015-09-29 20:55:07.920326521 -0600
@@ -232,7 +232,7 @@
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
-
+extern void drm_kms_helper_hdmi_hotplug_event(struct drm_device *dev);
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
diff -ruN linux-4.0.5/include/drm/drmP.h linux-4.0.5.new/include/drm/drmP.h
--- linux-4.0.5/include/drm/drmP.h 2015-08-16 21:52:51.000000000 -0600
+++ linux-4.0.5.new/include/drm/drmP.h 2015-09-29 21:57:15.171346051 -0600
@@ -1018,7 +1018,7 @@
/* sysfs support (drm_sysfs.c) */
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
-
+extern void drm_sysfs_hdmi_hotplug_event(struct drm_device *dev);
struct drm_device *drm_dev_alloc(struct drm_driver *driver,
struct device *parent);