diff options
author | Thierry Reding <treding@nvidia.com> | 2013-10-14 09:43:05 +0200 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2013-10-31 09:55:42 +0100 |
commit | 59af0595f4827e006f7f7804cc8656599a7772fe (patch) | |
tree | 8873b06616746a661b25205f492deb6d491950fa | |
parent | f27db9615ad6c0bad6047d0592cfc627b9997f8a (diff) | |
download | linux-next-59af0595f4827e006f7f7804cc8656599a7772fe.tar.gz |
drm/tegra: hdmi: Parameterize based on compatible property
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>
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 82 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.h | 1 |
2 files changed, 53 insertions, 30 deletions
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index ed7c58fa595c..745eec4e8fb8 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -17,6 +17,22 @@ #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", diff --git a/drivers/gpu/drm/tegra/hdmi.h b/drivers/gpu/drm/tegra/hdmi.h index 52ac36e08ccb..baf3cf343d71 100644 --- a/drivers/gpu/drm/tegra/hdmi.h +++ b/drivers/gpu/drm/tegra/hdmi.h @@ -233,7 +233,6 @@ #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 |