aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2013-10-14 03:43:05 -0400
committerThierry Reding <treding@nvidia.com>2013-10-31 04:55:42 -0400
commit59af0595f4827e006f7f7804cc8656599a7772fe (patch)
tree8873b06616746a661b25205f492deb6d491950fa
parentf27db9615ad6c0bad6047d0592cfc627b9997f8a (diff)
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.c82
-rw-r--r--drivers/gpu/drm/tegra/hdmi.h1
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 @@
17#include "drm.h" 17#include "drm.h"
18#include "dc.h" 18#include "dc.h"
19 19
20struct tmds_config {
21 unsigned int pclk;
22 u32 pll0;
23 u32 pll1;
24 u32 pe_current;
25 u32 drive_current;
26};
27
28struct tegra_hdmi_config {
29 const struct tmds_config *tmds;
30 unsigned int num_tmds;
31
32 unsigned long fuse_override_offset;
33 unsigned long fuse_override_value;
34};
35
20struct tegra_hdmi { 36struct tegra_hdmi {
21 struct host1x_client client; 37 struct host1x_client client;
22 struct tegra_output output; 38 struct tegra_output output;
@@ -31,6 +47,8 @@ struct tegra_hdmi {
31 struct clk *clk_parent; 47 struct clk *clk_parent;
32 struct clk *clk; 48 struct clk *clk;
33 49
50 const struct tegra_hdmi_config *config;
51
34 unsigned int audio_source; 52 unsigned int audio_source;
35 unsigned int audio_freq; 53 unsigned int audio_freq;
36 bool stereo; 54 bool stereo;
@@ -136,14 +154,6 @@ static const struct tegra_hdmi_audio_config tegra_hdmi_audio_192k[] = {
136 { 0, 0, 0, 0 }, 154 { 0, 0, 0, 0 },
137}; 155};
138 156
139struct tmds_config {
140 unsigned int pclk;
141 u32 pll0;
142 u32 pll1;
143 u32 pe_current;
144 u32 drive_current;
145};
146
147static const struct tmds_config tegra20_tmds_config[] = { 157static const struct tmds_config tegra20_tmds_config[] = {
148 { /* slow pixel clock modes */ 158 { /* slow pixel clock modes */
149 .pclk = 27000000, 159 .pclk = 27000000,
@@ -570,8 +580,12 @@ static void tegra_hdmi_setup_tmds(struct tegra_hdmi *hdmi,
570 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1); 580 tegra_hdmi_writel(hdmi, tmds->pll1, HDMI_NV_PDISP_SOR_PLL1);
571 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT); 581 tegra_hdmi_writel(hdmi, tmds->pe_current, HDMI_NV_PDISP_PE_CURRENT);
572 582
573 value = tmds->drive_current | DRIVE_CURRENT_FUSE_OVERRIDE; 583 tegra_hdmi_writel(hdmi, tmds->drive_current,
574 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT); 584 HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT);
585
586 value = tegra_hdmi_readl(hdmi, hdmi->config->fuse_override_offset);
587 value |= hdmi->config->fuse_override_value;
588 tegra_hdmi_writel(hdmi, value, hdmi->config->fuse_override_offset);
575} 589}
576 590
577static int tegra_output_hdmi_enable(struct tegra_output *output) 591static int tegra_output_hdmi_enable(struct tegra_output *output)
@@ -582,8 +596,6 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
582 struct tegra_hdmi *hdmi = to_hdmi(output); 596 struct tegra_hdmi *hdmi = to_hdmi(output);
583 struct device_node *node = hdmi->dev->of_node; 597 struct device_node *node = hdmi->dev->of_node;
584 unsigned int pulse_start, div82, pclk; 598 unsigned int pulse_start, div82, pclk;
585 const struct tmds_config *tmds;
586 unsigned int num_tmds;
587 unsigned long value; 599 unsigned long value;
588 int retries = 1000; 600 int retries = 1000;
589 int err; 601 int err;
@@ -703,17 +715,9 @@ static int tegra_output_hdmi_enable(struct tegra_output *output)
703 tegra_hdmi_setup_stereo_infoframe(hdmi); 715 tegra_hdmi_setup_stereo_infoframe(hdmi);
704 716
705 /* TMDS CONFIG */ 717 /* TMDS CONFIG */
706 if (of_device_is_compatible(node, "nvidia,tegra30-hdmi")) { 718 for (i = 0; i < hdmi->config->num_tmds; i++) {
707 num_tmds = ARRAY_SIZE(tegra30_tmds_config); 719 if (pclk <= hdmi->config->tmds[i].pclk) {
708 tmds = tegra30_tmds_config; 720 tegra_hdmi_setup_tmds(hdmi, &hdmi->config->tmds[i]);
709 } else {
710 num_tmds = ARRAY_SIZE(tegra20_tmds_config);
711 tmds = tegra20_tmds_config;
712 }
713
714 for (i = 0; i < num_tmds; i++) {
715 if (pclk <= tmds[i].pclk) {
716 tegra_hdmi_setup_tmds(hdmi, &tmds[i]);
717 break; 721 break;
718 } 722 }
719 } 723 }
@@ -1172,16 +1176,42 @@ static const struct host1x_client_ops hdmi_client_ops = {
1172 .exit = tegra_hdmi_exit, 1176 .exit = tegra_hdmi_exit,
1173}; 1177};
1174 1178
1179static const struct tegra_hdmi_config tegra20_hdmi_config = {
1180 .tmds = tegra20_tmds_config,
1181 .num_tmds = ARRAY_SIZE(tegra20_tmds_config),
1182 .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT,
1183 .fuse_override_value = 1 << 31,
1184};
1185
1186static const struct tegra_hdmi_config tegra30_hdmi_config = {
1187 .tmds = tegra30_tmds_config,
1188 .num_tmds = ARRAY_SIZE(tegra30_tmds_config),
1189 .fuse_override_offset = HDMI_NV_PDISP_SOR_LANE_DRIVE_CURRENT,
1190 .fuse_override_value = 1 << 31,
1191};
1192
1193static const struct of_device_id tegra_hdmi_of_match[] = {
1194 { .compatible = "nvidia,tegra30-hdmi", .data = &tegra30_hdmi_config },
1195 { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
1196 { },
1197};
1198
1175static int tegra_hdmi_probe(struct platform_device *pdev) 1199static int tegra_hdmi_probe(struct platform_device *pdev)
1176{ 1200{
1201 const struct of_device_id *match;
1177 struct tegra_hdmi *hdmi; 1202 struct tegra_hdmi *hdmi;
1178 struct resource *regs; 1203 struct resource *regs;
1179 int err; 1204 int err;
1180 1205
1206 match = of_match_node(tegra_hdmi_of_match, pdev->dev.of_node);
1207 if (!match)
1208 return -ENODEV;
1209
1181 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); 1210 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
1182 if (!hdmi) 1211 if (!hdmi)
1183 return -ENOMEM; 1212 return -ENOMEM;
1184 1213
1214 hdmi->config = match->data;
1185 hdmi->dev = &pdev->dev; 1215 hdmi->dev = &pdev->dev;
1186 hdmi->audio_source = AUTO; 1216 hdmi->audio_source = AUTO;
1187 hdmi->audio_freq = 44100; 1217 hdmi->audio_freq = 44100;
@@ -1284,12 +1314,6 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
1284 return 0; 1314 return 0;
1285} 1315}
1286 1316
1287static struct of_device_id tegra_hdmi_of_match[] = {
1288 { .compatible = "nvidia,tegra30-hdmi", },
1289 { .compatible = "nvidia,tegra20-hdmi", },
1290 { },
1291};
1292
1293struct platform_driver tegra_hdmi_driver = { 1317struct platform_driver tegra_hdmi_driver = {
1294 .driver = { 1318 .driver = {
1295 .name = "tegra-hdmi", 1319 .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 @@
233#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8) 233#define DRIVE_CURRENT_LANE1(x) (((x) & 0x3f) << 8)
234#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16) 234#define DRIVE_CURRENT_LANE2(x) (((x) & 0x3f) << 16)
235#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24) 235#define DRIVE_CURRENT_LANE3(x) (((x) & 0x3f) << 24)
236#define DRIVE_CURRENT_FUSE_OVERRIDE (1 << 31)
237 236
238#define DRIVE_CURRENT_1_500_mA 0x00 237#define DRIVE_CURRENT_1_500_mA 0x00
239#define DRIVE_CURRENT_1_875_mA 0x01 238#define DRIVE_CURRENT_1_875_mA 0x01