From 9be7d864cf0763dd24e07bac7f0a94180bd5e257 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 30 Aug 2013 15:22:36 +0200 Subject: 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 --- drivers/gpu/drm/tegra/output.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/tegra/output.c') diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 2cb0065e057..5dc4d1a9cad 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -9,6 +9,7 @@ #include +#include #include "drm.h" static int tegra_connector_get_modes(struct drm_connector *connector) @@ -17,6 +18,12 @@ static int tegra_connector_get_modes(struct drm_connector *connector) struct edid *edid = NULL; int err = 0; + if (output->panel) { + err = output->panel->funcs->get_modes(output->panel); + if (err > 0) + return err; + } + if (output->edid) edid = kmemdup(output->edid, sizeof(*edid), GFP_KERNEL); else if (output->ddc) @@ -72,6 +79,11 @@ tegra_connector_detect(struct drm_connector *connector, bool force) else status = connector_status_connected; } else { + if (!output->panel) + status = connector_status_disconnected; + else + status = connector_status_connected; + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) status = connector_status_connected; } @@ -115,6 +127,15 @@ static const struct drm_encoder_funcs encoder_funcs = { static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) { + struct tegra_output *output = encoder_to_output(encoder); + struct drm_panel *panel = output->panel; + + if (panel && panel->funcs) { + if (mode != DRM_MODE_DPMS_ON) + drm_panel_disable(panel); + else + drm_panel_enable(panel); + } } static bool tegra_encoder_mode_fixup(struct drm_encoder *encoder, @@ -163,14 +184,23 @@ static irqreturn_t hpd_irq(int irq, void *data) int tegra_output_probe(struct tegra_output *output) { + struct device_node *ddc, *panel; enum of_gpio_flags flags; - struct device_node *ddc; size_t size; int err; if (!output->of_node) output->of_node = output->dev->of_node; + panel = of_parse_phandle(output->of_node, "nvidia,panel", 0); + if (panel) { + output->panel = of_drm_find_panel(panel); + if (!output->panel) + return -EPROBE_DEFER; + + of_node_put(panel); + } + output->edid = of_get_property(output->of_node, "nvidia,edid", &size); ddc = of_parse_phandle(output->of_node, "nvidia,ddc-i2c-bus", 0); @@ -185,9 +215,6 @@ int tegra_output_probe(struct tegra_output *output) of_node_put(ddc); } - if (!output->edid && !output->ddc) - return -ENODEV; - output->hpd_gpio = of_get_named_gpio_flags(output->of_node, "nvidia,hpd-gpio", 0, &flags); @@ -267,6 +294,9 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) drm_connector_helper_add(&output->connector, &connector_helper_funcs); output->connector.dpms = DRM_MODE_DPMS_OFF; + if (output->panel) + drm_panel_attach(output->panel, &output->connector); + drm_encoder_init(drm, &output->encoder, &encoder_funcs, encoder); drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); -- cgit v1.2.3 From b5190022f77a41465c2202f621a5fa07c9aabb7b Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 29 Oct 2013 16:03:03 +0100 Subject: drm/tegra: Disable outputs for power-saving When an output is disabled, its DPMS mode is usually set to off. Instead of only disabling the panel (if one is attached), turn the output off entirely to save more power. HDMI doesn't have any panels attached, so it previously didn't save any power at all. With this commit, however, the complete HDMI interface will be turned off, therefore allowing an attached monitor to go into a standby mode. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/output.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/tegra/output.c') diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 5dc4d1a9cad..581dc5d37be 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -130,11 +130,12 @@ static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) struct tegra_output *output = encoder_to_output(encoder); struct drm_panel *panel = output->panel; - if (panel && panel->funcs) { - if (mode != DRM_MODE_DPMS_ON) - drm_panel_disable(panel); - else - drm_panel_enable(panel); + if (mode != DRM_MODE_DPMS_ON) { + drm_panel_disable(panel); + tegra_output_disable(output); + } else { + tegra_output_enable(output); + drm_panel_enable(panel); } } -- cgit v1.2.3 From dec727399a4b36bec87b7b4d4c1b20025e69758a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 3 Sep 2013 08:45:46 +0200 Subject: drm/tegra: Add DSI support This commit adds support for both DSI outputs found on Tegra. Only very minimal functionality is implemented, so advanced features like ganged mode won't work. Due to the lack of other test hardware, some sections of the driver are hardcoded to work with Dalmore. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/output.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/tegra/output.c') diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 581dc5d37be..f1b5030f55e 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -284,6 +284,11 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) encoder = DRM_MODE_ENCODER_TMDS; break; + case TEGRA_OUTPUT_DSI: + connector = DRM_MODE_CONNECTOR_DSI; + encoder = DRM_MODE_ENCODER_DSI; + break; + default: connector = DRM_MODE_CONNECTOR_Unknown; encoder = DRM_MODE_ENCODER_NONE; -- cgit v1.2.3