Merge tag 'drm/for-3.14-rc1-20140123' of git://anongit.freedesktop.org/tegra/linux...
authorDave Airlie <airlied@redhat.com>
Wed, 29 Jan 2014 02:03:56 +0000 (12:03 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 29 Jan 2014 02:03:56 +0000 (12:03 +1000)
drm/tegra: Changes for v3.14-rc1 (update)

These patches fix some issues caused by the DRM panel support from the
previous pull request and add two more panels (for the Toshiba AC100 as
well as the Seaboard and Ventana).

* tag 'drm/for-3.14-rc1-20140123' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: Obtain head number from DT
  drm/panel: update EDID BLOB in panel_simple_get_modes()
  gpu: host1x: Remove unnecessary include
  drm/tegra: Use proper data type
  drm/tegra: Clarify how panel modes override others
  drm/tegra: Fix possible CRTC mask for RGB outputs
  drm/i915: Use drm_encoder_crtc_ok()
  drm: Move drm_encoder_crtc_ok() to core
  drm: provide a helper for the encoder possible_crtcs mask
  drm/tegra: Don't check resource with devm_ioremap_resource()
  drm/panel: Add support for Chunghwa CLAA101WA01A panel
  drm/panel: Add support for Samsung LTN101NT05 panel

13 files changed:
Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
Documentation/devicetree/bindings/panel/chunghwa,claa101wa01a.txt [new file with mode: 0644]
Documentation/devicetree/bindings/panel/samsung,ltn101nt05.txt [new file with mode: 0644]
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/hdmi.c
drivers/gpu/drm/tegra/output.c
drivers/gpu/drm/tegra/rgb.c
drivers/gpu/host1x/hw/intr_hw.c
include/drm/drm_crtc.h

index 9e9008f8fa3231905428d8e1b62cf2a864008b31..efaeec8961b64bddba0df9d48af9af65e630f659 100644 (file)
@@ -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 (file)
index 0000000..f24614e
--- /dev/null
@@ -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 (file)
index 0000000..ef522c6
--- /dev/null
@@ -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.
index 266a01d7f6353db7a5e28d23a86215e85bf18d78..3b7d32da16046ffcdc238ba41b1b03a3ec152435 100644 (file)
@@ -674,6 +674,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
index 245fe4fa9c9edd5b36ca2448652020558edb3e8c..ea92b827e787e3543a745b119822085618c16988 100644 (file)
@@ -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
index 40a9338ad54f1fbe12f1c00930356396f92736e5..9fa24347963a38d360e365cfa20bf7cefed8beaa 100644 (file)
@@ -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);
index 3e611afc93f475723d11e3c8f4b834c71f4a8d9f..59d52ca2c67fdf6caaf9e1729998f2a24b20813e 100644 (file)
@@ -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,13 +361,41 @@ 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",
        }, {
index 386f3b4b00940660f72c889e91b8068ad34e9af4..9336006b475d70b7494f1694d8661c07c2cd882a 100644 (file)
@@ -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");
index bc9cb1ac709b197f628bd585c875ee1ba7c95dc3..6928015d11a49e9fd6e499aed2ed5f02d6d1730e 100644 (file)
@@ -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);
index f1b5030f55e33e8c78a3f0c2c1b24528a3fd12aa..57cecbd18ca88d210a6e83e61c3f3cff208f26e5 100644 (file)
@@ -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;
index 03885bb8dcc049bed4f25c16fceef22968a72d51..338f7f6561d701d601a92b2f6362782536d03e2e 100644 (file)
@@ -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;
 }
index b26dcc83bc1b373400d72c46aad21d04fb97f52f..db9017adfe2bb944f01558f49769f60715995c87 100644 (file)
@@ -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"
index e963470efd3998126f56621752cd2ba326c2131c..71727b6210ae57d5b064be1cab19a4dc660df6f8 100644 (file)
@@ -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,