summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt3
-rw-r--r--Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt7
-rw-r--r--Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt7
-rw-r--r--drivers/gpu/drm/drm_crtc.c23
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c29
-rw-r--r--drivers/gpu/drm/i915/intel_display.c26
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c51
-rw-r--r--drivers/gpu/drm/tegra/dc.c41
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c3
-rw-r--r--drivers/gpu/drm/tegra/output.c7
-rw-r--r--drivers/gpu/drm/tegra/rgb.c2
-rw-r--r--drivers/gpu/host1x/hw/intr_hw.c1
-rw-r--r--include/drm/drm_crtc.h26
13 files changed, 164 insertions, 62 deletions
diff --git a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
index 9e9008f8fa32..efaeec8961b6 100644
--- a/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
+++ b/Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
@@ -118,6 +118,9 @@ of the following host1x client modules:
See ../reset/reset.txt for details.
- reset-names: Must include the following entries:
- dc
+ - nvidia,head: The number of the display controller head. This is used to
+ setup the various types of output to receive video data from the given
+ head.
Each display controller node has a child node, named "rgb", that represents
the RGB output associated with the controller. It can take the following
diff --git a/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt b/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt
new file mode 100644
index 000000000000..f24614e4d5ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 10.1" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa101wa01a"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt b/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt
new file mode 100644
index 000000000000..ef522c6bb85f
--- /dev/null
+++ b/Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt
@@ -0,0 +1,7 @@
+Samsung Electronics 10.1" WSVGA TFT LCD panel
+
+Required properties:
+- compatible: should be "samsung,ltn101nt05"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 266a01d7f635..3b7d32da1604 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -675,6 +675,29 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
EXPORT_SYMBOL(drm_crtc_cleanup);
/**
+ * drm_crtc_index - find the index of a registered CRTC
+ * @crtc: CRTC to find index for
+ *
+ * Given a registered CRTC, return the index of that CRTC within a DRM
+ * device's list of CRTCs.
+ */
+unsigned int drm_crtc_index(struct drm_crtc *crtc)
+{
+ unsigned int index = 0;
+ struct drm_crtc *tmp;
+
+ list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
+ if (tmp == crtc)
+ return index;
+
+ index++;
+ }
+
+ BUG();
+}
+EXPORT_SYMBOL(drm_crtc_index);
+
+/**
* drm_mode_probed_add - add a mode to a connector's probed mode list
* @connector: connector the new mode
* @mode: mode data
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 245fe4fa9c9e..ea92b827e787 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -324,35 +324,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_helper_disable_unused_functions);
-/**
- * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
- * @encoder: encoder to test
- * @crtc: crtc to test
- *
- * Return false if @encoder can't be driven by @crtc, true otherwise.
- */
-static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
- struct drm_crtc *crtc)
-{
- struct drm_device *dev;
- struct drm_crtc *tmp;
- int crtc_mask = 1;
-
- WARN(!crtc, "checking null crtc?\n");
-
- dev = crtc->dev;
-
- list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
- if (tmp == crtc)
- break;
- crtc_mask <<= 1;
- }
-
- if (encoder->possible_crtcs & crtc_mask)
- return true;
- return false;
-}
-
/*
* Check the CRTC we're going to map each output to vs. its current
* CRTC. If they don't match, we have to disable the output and the CRTC
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 40a9338ad54f..9fa24347963a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8744,28 +8744,6 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = {
.load_lut = intel_crtc_load_lut,
};
-static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
- struct drm_crtc *crtc)
-{
- struct drm_device *dev;
- struct drm_crtc *tmp;
- int crtc_mask = 1;
-
- WARN(!crtc, "checking null crtc?\n");
-
- dev = crtc->dev;
-
- list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
- if (tmp == crtc)
- break;
- crtc_mask <<= 1;
- }
-
- if (encoder->possible_crtcs & crtc_mask)
- return true;
- return false;
-}
-
/**
* intel_modeset_update_staged_output_state
*
@@ -9940,8 +9918,8 @@ intel_modeset_stage_output_state(struct drm_device *dev,
}
/* Make sure the new CRTC will work with the encoder */
- if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
- new_crtc)) {
+ if (!drm_encoder_crtc_ok(&connector->new_encoder->base,
+ new_crtc)) {
return -EINVAL;
}
connector->encoder->new_crtc = to_intel_crtc(new_crtc);
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 3e611afc93f4..59d52ca2c67f 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -162,6 +162,7 @@ static int panel_simple_get_modes(struct drm_panel *panel)
/* probe EDID if a DDC bus is available */
if (p->ddc) {
struct edid *edid = drm_get_edid(panel->connector, p->ddc);
+ drm_mode_connector_update_edid_property(panel->connector, edid);
if (edid) {
num += drm_add_edid_modes(panel->connector, edid);
kfree(edid);
@@ -316,6 +317,28 @@ static const struct panel_desc auo_b101aw03 = {
},
};
+static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
+ .clock = 72070,
+ .hdisplay = 1366,
+ .hsync_start = 1366 + 58,
+ .hsync_end = 1366 + 58 + 58,
+ .htotal = 1366 + 58 + 58 + 58,
+ .vdisplay = 768,
+ .vsync_start = 768 + 4,
+ .vsync_end = 768 + 4 + 4,
+ .vtotal = 768 + 4 + 4 + 4,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc chunghwa_claa101wa01a = {
+ .modes = &chunghwa_claa101wa01a_mode,
+ .num_modes = 1,
+ .size = {
+ .width = 220,
+ .height = 120,
+ },
+};
+
static const struct drm_display_mode chunghwa_claa101wb01_mode = {
.clock = 69300,
.hdisplay = 1366,
@@ -338,14 +361,42 @@ static const struct panel_desc chunghwa_claa101wb01 = {
},
};
+static const struct drm_display_mode samsung_ltn101nt05_mode = {
+ .clock = 54030,
+ .hdisplay = 1024,
+ .hsync_start = 1024 + 24,
+ .hsync_end = 1024 + 24 + 136,
+ .htotal = 1024 + 24 + 136 + 160,
+ .vdisplay = 600,
+ .vsync_start = 600 + 3,
+ .vsync_end = 600 + 3 + 6,
+ .vtotal = 600 + 3 + 6 + 61,
+ .vrefresh = 60,
+};
+
+static const struct panel_desc samsung_ltn101nt05 = {
+ .modes = &samsung_ltn101nt05_mode,
+ .num_modes = 1,
+ .size = {
+ .width = 1024,
+ .height = 600,
+ },
+};
+
static const struct of_device_id platform_of_match[] = {
{
.compatible = "auo,b101aw03",
.data = &auo_b101aw03,
}, {
+ .compatible = "chunghwa,claa101wa01a",
+ .data = &chunghwa_claa101wa01a
+ }, {
.compatible = "chunghwa,claa101wb01",
.data = &chunghwa_claa101wb01
}, {
+ .compatible = "samsung,ltn101nt05",
+ .data = &samsung_ltn101nt05,
+ }, {
.compatible = "simple-panel",
}, {
/* sentinel */
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 386f3b4b0094..9336006b475d 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1100,8 +1100,6 @@ static int tegra_dc_init(struct host1x_client *client)
struct tegra_dc *dc = host1x_client_to_dc(client);
int err;
- dc->pipe = tegra->drm->mode_config.num_crtc;
-
drm_crtc_init(tegra->drm, &dc->base, &tegra_crtc_funcs);
drm_mode_crtc_set_gamma_size(&dc->base, 256);
drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
@@ -1187,6 +1185,41 @@ static const struct of_device_id tegra_dc_of_match[] = {
}
};
+static int tegra_dc_parse_dt(struct tegra_dc *dc)
+{
+ struct device_node *np;
+ u32 value = 0;
+ int err;
+
+ err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
+ if (err < 0) {
+ dev_err(dc->dev, "missing \"nvidia,head\" property\n");
+
+ /*
+ * If the nvidia,head property isn't present, try to find the
+ * correct head number by looking up the position of this
+ * display controller's node within the device tree. Assuming
+ * that the nodes are ordered properly in the DTS file and
+ * that the translation into a flattened device tree blob
+ * preserves that ordering this will actually yield the right
+ * head number.
+ *
+ * If those assumptions don't hold, this will still work for
+ * cases where only a single display controller is used.
+ */
+ for_each_matching_node(np, tegra_dc_of_match) {
+ if (np == dc->dev->of_node)
+ break;
+
+ value++;
+ }
+ }
+
+ dc->pipe = value;
+
+ return 0;
+}
+
static int tegra_dc_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
@@ -1207,6 +1240,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
dc->dev = &pdev->dev;
dc->soc = id->data;
+ err = tegra_dc_parse_dt(dc);
+ if (err < 0)
+ return err;
+
dc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dc->clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index bc9cb1ac709b..6928015d11a4 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1418,9 +1418,6 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
return err;
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs)
- return -ENXIO;
-
hdmi->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(hdmi->regs))
return PTR_ERR(hdmi->regs);
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index f1b5030f55e3..57cecbd18ca8 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -18,6 +18,10 @@ static int tegra_connector_get_modes(struct drm_connector *connector)
struct edid *edid = NULL;
int err = 0;
+ /*
+ * If the panel provides one or more modes, use them exclusively and
+ * ignore any other means of obtaining a mode.
+ */
if (output->panel) {
err = output->panel->funcs->get_modes(output->panel);
if (err > 0)
@@ -187,8 +191,7 @@ int tegra_output_probe(struct tegra_output *output)
{
struct device_node *ddc, *panel;
enum of_gpio_flags flags;
- size_t size;
- int err;
+ int err, size;
if (!output->of_node)
output->of_node = output->dev->of_node;
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index 03885bb8dcc0..338f7f6561d7 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -258,7 +258,7 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
* RGB outputs are an exception, so we make sure they can be attached
* to only their parent display controller.
*/
- rgb->output.encoder.possible_crtcs = 1 << dc->pipe;
+ rgb->output.encoder.possible_crtcs = drm_crtc_mask(&dc->base);
return 0;
}
diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c
index b26dcc83bc1b..db9017adfe2b 100644
--- a/drivers/gpu/host1x/hw/intr_hw.c
+++ b/drivers/gpu/host1x/hw/intr_hw.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
-#include <asm/mach/irq.h>
#include "../intr.h"
#include "../dev.h"
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e963470efd39..71727b6210ae 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -931,6 +931,19 @@ extern int drm_crtc_init(struct drm_device *dev,
struct drm_crtc *crtc,
const struct drm_crtc_funcs *funcs);
extern void drm_crtc_cleanup(struct drm_crtc *crtc);
+extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
+
+/**
+ * drm_crtc_mask - find the mask of a registered CRTC
+ * @crtc: CRTC to find mask for
+ *
+ * Given a registered CRTC, return the mask bit of that CRTC for an
+ * encoder's possible_crtcs field.
+ */
+static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
+{
+ return 1 << drm_crtc_index(crtc);
+}
extern void drm_connector_ida_init(void);
extern void drm_connector_ida_destroy(void);
@@ -952,6 +965,19 @@ extern int drm_encoder_init(struct drm_device *dev,
const struct drm_encoder_funcs *funcs,
int encoder_type);
+/**
+ * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
+ * @encoder: encoder to test
+ * @crtc: crtc to test
+ *
+ * Return false if @encoder can't be driven by @crtc, true otherwise.
+ */
+static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
+ struct drm_crtc *crtc)
+{
+ return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
+}
+
extern int drm_plane_init(struct drm_device *dev,
struct drm_plane *plane,
unsigned long possible_crtcs,