drm/tegra: Add Tegra124 DC support
authorThierry Reding <treding@nvidia.com>
Thu, 12 Dec 2013 10:03:59 +0000 (11:03 +0100)
committerThierry Reding <treding@nvidia.com>
Fri, 20 Dec 2013 14:56:06 +0000 (15:56 +0100)
Tegra124 and later support interlacing, but the driver doesn't support
it yet. Make sure interlacing stays disabled on hardware that supports
it.

Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/dc.h
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tegra/drm.h

index cd7f1e4..f89445d 100644 (file)
 #include "drm.h"
 #include "gem.h"
 
+struct tegra_dc_soc_info {
+       bool supports_interlacing;
+};
+
 struct tegra_plane {
        struct drm_plane base;
        unsigned int index;
@@ -658,6 +662,13 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc,
        /* program display mode */
        tegra_dc_set_timings(dc, mode);
 
+       /* interlacing isn't supported yet, so disable it */
+       if (dc->soc->supports_interlacing) {
+               value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
+               value &= ~INTERLACE_ENABLE;
+               tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
+       }
+
        value = DE_SELECT_ACTIVE | DE_CONTROL_NORMAL;
        tegra_dc_writel(dc, value, DC_DISP_DATA_ENABLE_OPTIONS);
 
@@ -1167,8 +1178,36 @@ static const struct host1x_client_ops dc_client_ops = {
        .exit = tegra_dc_exit,
 };
 
+static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
+       .supports_interlacing = false,
+};
+
+static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
+       .supports_interlacing = false,
+};
+
+static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
+       .supports_interlacing = true,
+};
+
+static const struct of_device_id tegra_dc_of_match[] = {
+       {
+               .compatible = "nvidia,tegra124-dc",
+               .data = &tegra124_dc_soc_info,
+       }, {
+               .compatible = "nvidia,tegra30-dc",
+               .data = &tegra30_dc_soc_info,
+       }, {
+               .compatible = "nvidia,tegra20-dc",
+               .data = &tegra20_dc_soc_info,
+       }, {
+               /* sentinel */
+       }
+};
+
 static int tegra_dc_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *id;
        struct resource *regs;
        struct tegra_dc *dc;
        int err;
@@ -1177,9 +1216,14 @@ static int tegra_dc_probe(struct platform_device *pdev)
        if (!dc)
                return -ENOMEM;
 
+       id = of_match_node(tegra_dc_of_match, pdev->dev.of_node);
+       if (!id)
+               return -ENODEV;
+
        spin_lock_init(&dc->lock);
        INIT_LIST_HEAD(&dc->list);
        dc->dev = &pdev->dev;
+       dc->soc = id->data;
 
        dc->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dc->clk)) {
@@ -1253,12 +1297,6 @@ static int tegra_dc_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_dc_of_match[] = {
-       { .compatible = "nvidia,tegra30-dc", },
-       { .compatible = "nvidia,tegra20-dc", },
-       { },
-};
-
 struct platform_driver tegra_dc_driver = {
        .driver = {
                .name = "tegra-dc",
index 788627a..e6a9df0 100644 (file)
 #define DC_DISP_SD_HW_K_VALUES                 0x4dd
 #define DC_DISP_SD_MAN_K_VALUES                        0x4de
 
+#define DC_DISP_INTERLACE_CONTROL              0x4e5
+#define  INTERLACE_STATUS (1 << 2)
+#define  INTERLACE_START  (1 << 1)
+#define  INTERLACE_ENABLE (1 << 0)
+
 #define DC_WIN_CSC_YOF                         0x611
 #define DC_WIN_CSC_KYRGB                       0x612
 #define DC_WIN_CSC_KUR                         0x613
index a0b3481..eec8d2e 100644 (file)
@@ -658,6 +658,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
        { .compatible = "nvidia,tegra114-dsi", },
        { .compatible = "nvidia,tegra114-hdmi", },
        { .compatible = "nvidia,tegra114-gr3d", },
+       { .compatible = "nvidia,tegra124-dc", },
        { /* sentinel */ }
 };
 
index 6b293c8..bf1cac7 100644 (file)
@@ -88,6 +88,7 @@ extern int tegra_drm_unregister_client(struct tegra_drm *tegra,
 extern int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 extern int tegra_drm_exit(struct tegra_drm *tegra);
 
+struct tegra_dc_soc_info;
 struct tegra_output;
 
 struct tegra_dc {
@@ -113,6 +114,8 @@ struct tegra_dc {
 
        /* page-flip handling */
        struct drm_pending_vblank_event *event;
+
+       const struct tegra_dc_soc_info *soc;
 };
 
 static inline struct tegra_dc *