]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/tegra: hdmi: Parameterize based on compatible property
authorThierry Reding <treding@nvidia.com>
Mon, 14 Oct 2013 07:43:05 +0000 (09:43 +0200)
committerThierry Reding <treding@nvidia.com>
Wed, 16 Oct 2013 18:03:00 +0000 (20:03 +0200)
Use a structure to parameterize the code to handle differences between
the HDMI hardware on various SoC generations. This removes the need to
clutter the code with checks for individual compatible values.

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

index ed7c58fa595c8f293c637bdec127b85f1c5bd94e..745eec4e8fb88612a5e28215372ba3ddc221329a 100644 (file)
 #include "drm.h"
 #include "dc.h"
 
+struct tmds_config {
+       unsigned int pclk;
+       u32 pll0;
+       u32 pll1;
+       u32 pe_current;
+       u32 drive_current;
+};
+
+struct tegra_hdmi_config {
+       const struct tmds_config *tmds;
+       unsigned int num_tmds;
+
+       unsigned long fuse_override_offset;
+       unsigned long fuse_override_value;
+};
+
 struct tegra_hdmi {
        struct host1x_client client;
        struct tegra_output output;
@@ -31,6 +47,8 @@ struct tegra_hdmi {
        struct clk *clk_parent;
        struct clk *clk;
 
+       const struct tegra_hdmi_config *config;
+
        unsigned int audio_source;
        unsigned int audio_freq;
        bool stereo;
@@ -136,14 +154,6 @@ static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
        {         0,     0,      0,     0 },
 };
 
-struct tmds_config {
-       unsigned int pclk;
-       u32 pll0;
-       u32 pll1;
-       u32 pe_current;
-       u32 drive_current;
-};
-
 static const struct tmds_config tegra20_tmds_config[] = {
        { /* slow pixel clock modes */
                .pclk = 27000000,
@@ -570,8 +580,12 @@ static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
        tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
        tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
 
-       value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE;
-       tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+       tegra_hdmi_writel(hdmi, tmds->drive_current,
+                         HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
+
+       value = tegra_hdmi_readl(hdmi, hdmi->config->fuse_override_offset);
+       value |= hdmi->config->fuse_override_value;
+       tegra_hdmi_writel(hdmi, value, hdmi->config->fuse_override_offset);
 }
 
 static int tegra_output_hdmi_enable(struct tegra_output *output)
@@ -582,8 +596,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
        struct tegra_hdmi *hdmi = to_hdmi(output);
        struct device_node *node = hdmi->dev->of_node;
        unsigned int pulse_start, div82, pclk;
-       const struct tmds_config *tmds;
-       unsigned int num_tmds;
        unsigned long value;
        int retries = 1000;
        int err;
@@ -703,17 +715,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
        tegra_hdmi_setup_stereo_infoframe(hdmi);
 
        /* TMDS CONFIG */
-       if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) {
-               num_tmds = ARRAY_SIZE(tegra30_tmds_config);
-               tmds = tegra30_tmds_config;
-       } else {
-               num_tmds = ARRAY_SIZE(tegra20_tmds_config);
-               tmds = tegra20_tmds_config;
-       }
-
-       for (i = 0; i < num_tmds; i++) {
-               if (pclk <= tmds[i].pclk) {
-                       tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
+       for (i = 0; i < hdmi->config->num_tmds; i++) {
+               if (pclk <= hdmi->config->tmds[i].pclk) {
+                       tegra_hdmi_setup_tmds(hdmi, &hdmi->config->tmds[i]);
                        break;
                }
        }
@@ -1172,16 +1176,42 @@ static const struct host1x_client_ops hdmi_client_ops = {
        .exit = tegra_hdmi_exit,
 };
 
+static const struct tegra_hdmi_config tegra20_hdmi_config = {
+       .tmds = tegra20_tmds_config,
+       .num_tmds = ARRAY_SIZE(tegra20_tmds_config),
+       .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT,
+       .fuse_override_value = 1 << 31,
+};
+
+static const struct tegra_hdmi_config tegra30_hdmi_config = {
+       .tmds = tegra30_tmds_config,
+       .num_tmds = ARRAY_SIZE(tegra30_tmds_config),
+       .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT,
+       .fuse_override_value = 1 << 31,
+};
+
+static const struct of_device_id tegra_hdmi_of_match[] = {
+       { .compatible = "nvidia,tegra30-hdmi", .data = &tegra30_hdmi_config },
+       { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
+       { },
+};
+
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *match;
        struct tegra_hdmi *hdmi;
        struct resource *regs;
        int err;
 
+       match = of_match_node(tegra_hdmi_of_match, pdev->dev.of_node);
+       if (!match)
+               return -ENODEV;
+
        hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
        if (!hdmi)
                return -ENOMEM;
 
+       hdmi->config = match->data;
        hdmi->dev = &pdev->dev;
        hdmi->audio_source = AUTO;
        hdmi->audio_freq = 44100;
@@ -1284,12 +1314,6 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tegra_hdmi_of_match[] = {
-       { .compatible = "nvidia,tegra30-hdmi", },
-       { .compatible = "nvidia,tegra20-hdmi", },
-       { },
-};
-
 struct platform_driver tegra_hdmi_driver = {
        .driver = {
                .name = "tegra-hdmi",
index 52ac36e08ccbef5ec14df106abeabcdd12efe6f2..baf3cf343d71453a15eb5cf1d1a2c7a7d028afda 100644 (file)
 #define DRIVE_CURRENT_LANE1(x)      (((x) & 0x3f) <<  8)
 #define DRIVE_CURRENT_LANE2(x)      (((x) & 0x3f) << 16)
 #define DRIVE_CURRENT_LANE3(x)      (((x) & 0x3f) << 24)
-#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
 
 #define DRIVE_CURRENT_1_500_mA  0x00
 #define DRIVE_CURRENT_1_875_mA  0x01