diff options
author | Thierry Reding <treding@nvidia.com> | 2013-08-30 09:22:36 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2013-12-17 12:10:00 -0500 |
commit | 9be7d864cf0763dd24e07bac7f0a94180bd5e257 (patch) | |
tree | 5463360e4af4ded1a4e6d18982a415192bbd9c81 | |
parent | 210fcd9d9cf1ad6ebfae3b46b457e602c8f8cdc2 (diff) |
drm/tegra: Implement panel support
Use the DRM panel framework to attach a panel to an output. If the panel
attached to a connector supports supports the backlight brightness
accessors, a property will be available to allow the brightness to be
modified from userspace.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/output.c | 38 |
4 files changed, 38 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt index ab45c02aa658..31314bd40da9 100644 --- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt +++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt | |||
@@ -125,6 +125,7 @@ of the following host1x client modules: | |||
125 | - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing | 125 | - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing |
126 | - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection | 126 | - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection |
127 | - nvidia,edid: supplies a binary EDID blob | 127 | - nvidia,edid: supplies a binary EDID blob |
128 | - nvidia,panel: phandle of a display panel | ||
128 | 129 | ||
129 | - hdmi: High Definition Multimedia Interface | 130 | - hdmi: High Definition Multimedia Interface |
130 | 131 | ||
@@ -149,6 +150,7 @@ of the following host1x client modules: | |||
149 | - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing | 150 | - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing |
150 | - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection | 151 | - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection |
151 | - nvidia,edid: supplies a binary EDID blob | 152 | - nvidia,edid: supplies a binary EDID blob |
153 | - nvidia,panel: phandle of a display panel | ||
152 | 154 | ||
153 | - tvo: TV encoder output | 155 | - tvo: TV encoder output |
154 | 156 | ||
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index 8db9b3bce001..1b5448cd6829 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig | |||
@@ -6,6 +6,7 @@ config DRM_TEGRA | |||
6 | select TEGRA_HOST1X | 6 | select TEGRA_HOST1X |
7 | select DRM_KMS_HELPER | 7 | select DRM_KMS_HELPER |
8 | select DRM_KMS_FB_HELPER | 8 | select DRM_KMS_FB_HELPER |
9 | select DRM_PANEL | ||
9 | select FB_SYS_FILLRECT | 10 | select FB_SYS_FILLRECT |
10 | select FB_SYS_COPYAREA | 11 | select FB_SYS_COPYAREA |
11 | select FB_SYS_IMAGEBLIT | 12 | select FB_SYS_IMAGEBLIT |
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 266aae08a3bd..bb8b1305606e 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
@@ -186,6 +186,7 @@ struct tegra_output { | |||
186 | const struct tegra_output_ops *ops; | 186 | const struct tegra_output_ops *ops; |
187 | enum tegra_output_type type; | 187 | enum tegra_output_type type; |
188 | 188 | ||
189 | struct drm_panel *panel; | ||
189 | struct i2c_adapter *ddc; | 190 | struct i2c_adapter *ddc; |
190 | const struct edid *edid; | 191 | const struct edid *edid; |
191 | unsigned int hpd_irq; | 192 | unsigned int hpd_irq; |
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 2cb0065e0578..5dc4d1a9cad8 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/of_gpio.h> | 10 | #include <linux/of_gpio.h> |
11 | 11 | ||
12 | #include <drm/drm_panel.h> | ||
12 | #include "drm.h" | 13 | #include "drm.h" |
13 | 14 | ||
14 | static int tegra_connector_get_modes(struct drm_connector *connector) | 15 | static int tegra_connector_get_modes(struct drm_connector *connector) |
@@ -17,6 +18,12 @@ static int tegra_connector_get_modes(struct drm_connector *connector) | |||
17 | struct edid *edid = NULL; | 18 | struct edid *edid = NULL; |
18 | int err = 0; | 19 | int err = 0; |
19 | 20 | ||
21 | if (output->panel) { | ||
22 | err = output->panel->funcs->get_modes(output->panel); | ||
23 | if (err > 0) | ||
24 | return err; | ||
25 | } | ||
26 | |||
20 | if (output->edid) | 27 | if (output->edid) |
21 | edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); | 28 | edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); |
22 | else if (output->ddc) | 29 | else if (output->ddc) |
@@ -72,6 +79,11 @@ tegra_connector_detect(struct drm_connector *connector, bool force) | |||
72 | else | 79 | else |
73 | status = connector_status_connected; | 80 | status = connector_status_connected; |
74 | } else { | 81 | } else { |
82 | if (!output->panel) | ||
83 | status = connector_status_disconnected; | ||
84 | else | ||
85 | status = connector_status_connected; | ||
86 | |||
75 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) | 87 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) |
76 | status = connector_status_connected; | 88 | status = connector_status_connected; |
77 | } | 89 | } |
@@ -115,6 +127,15 @@ static const struct drm_encoder_funcs encoder_funcs = { | |||
115 | 127 | ||
116 | static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) | 128 | static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) |
117 | { | 129 | { |
130 | struct tegra_output *output = encoder_to_output(encoder); | ||
131 | struct drm_panel *panel = output->panel; | ||
132 | |||
133 | if (panel && panel->funcs) { | ||
134 | if (mode != DRM_MODE_DPMS_ON) | ||
135 | drm_panel_disable(panel); | ||
136 | else | ||
137 | drm_panel_enable(panel); | ||
138 | } | ||
118 | } | 139 | } |
119 | 140 | ||
120 | static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder, | 141 | static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder, |
@@ -163,14 +184,23 @@ static irqreturn_t hpd_irq(int irq, void *data) | |||
163 | 184 | ||
164 | int tegra_output_probe(struct tegra_output *output) | 185 | int tegra_output_probe(struct tegra_output *output) |
165 | { | 186 | { |
187 | struct device_node *ddc, *panel; | ||
166 | enum of_gpio_flags flags; | 188 | enum of_gpio_flags flags; |
167 | struct device_node *ddc; | ||
168 | size_t size; | 189 | size_t size; |
169 | int err; | 190 | int err; |
170 | 191 | ||
171 | if (!output->of_node) | 192 | if (!output->of_node) |
172 | output->of_node = output->dev->of_node; | 193 | output->of_node = output->dev->of_node; |
173 | 194 | ||
195 | panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); | ||
196 | if (panel) { | ||
197 | output->panel = of_drm_find_panel(panel); | ||
198 | if (!output->panel) | ||
199 | return -EPROBE_DEFER; | ||
200 | |||
201 | of_node_put(panel); | ||
202 | } | ||
203 | |||
174 | output->edid = of_get_property(output->of_node, "nvidia,edid", &size); | 204 | output->edid = of_get_property(output->of_node, "nvidia,edid", &size); |
175 | 205 | ||
176 | ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); | 206 | ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); |
@@ -185,9 +215,6 @@ int tegra_output_probe(struct tegra_output *output) | |||
185 | of_node_put(ddc); | 215 | of_node_put(ddc); |
186 | } | 216 | } |
187 | 217 | ||
188 | if (!output->edid && !output->ddc) | ||
189 | return -ENODEV; | ||
190 | |||
191 | output->hpd_gpio = of_get_named_gpio_flags(output->of_node, | 218 | output->hpd_gpio = of_get_named_gpio_flags(output->of_node, |
192 | "nvidia,hpd-gpio", 0, | 219 | "nvidia,hpd-gpio", 0, |
193 | &flags); | 220 | &flags); |
@@ -267,6 +294,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) | |||
267 | drm_connector_helper_add(&output->connector, &connector_helper_funcs); | 294 | drm_connector_helper_add(&output->connector, &connector_helper_funcs); |
268 | output->connector.dpms = DRM_MODE_DPMS_OFF; | 295 | output->connector.dpms = DRM_MODE_DPMS_OFF; |
269 | 296 | ||
297 | if (output->panel) | ||
298 | drm_panel_attach(output->panel, &output->connector); | ||
299 | |||
270 | drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); | 300 | drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); |
271 | drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); | 301 | drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); |
272 | 302 | ||