aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/dss/Makefile2
-rw-r--r--drivers/video/omap2/dss/dss_features.c3
-rw-r--r--drivers/video/omap2/dss/hdmi.c65
-rw-r--r--drivers/video/omap2/dss/hdmi_pll.c261
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h25
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c132
6 files changed, 285 insertions, 203 deletions
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 56ce6bd36905..5ea65d327cfb 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -10,5 +10,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o hdmi_wp.o ti_hdmi_4xxx_ip.o 13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o hdmi_wp.o hdmi_pll.o ti_hdmi_4xxx_ip.o
14ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG 14ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index db359e8df503..9ee92e90caff 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -797,10 +797,7 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
797 .phy_enable = ti_hdmi_4xxx_phy_enable, 797 .phy_enable = ti_hdmi_4xxx_phy_enable,
798 .phy_disable = ti_hdmi_4xxx_phy_disable, 798 .phy_disable = ti_hdmi_4xxx_phy_disable,
799 .read_edid = ti_hdmi_4xxx_read_edid, 799 .read_edid = ti_hdmi_4xxx_read_edid,
800 .pll_enable = ti_hdmi_4xxx_pll_enable,
801 .pll_disable = ti_hdmi_4xxx_pll_disable,
802 .dump_core = ti_hdmi_4xxx_core_dump, 800 .dump_core = ti_hdmi_4xxx_core_dump,
803 .dump_pll = ti_hdmi_4xxx_pll_dump,
804 .dump_phy = ti_hdmi_4xxx_phy_dump, 801 .dump_phy = ti_hdmi_4xxx_phy_dump,
805#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 802#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
806 .audio_start = ti_hdmi_4xxx_audio_start, 803 .audio_start = ti_hdmi_4xxx_audio_start,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index f2475fc1b632..f6a2eba244e7 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -42,7 +42,6 @@
42 42
43#define HDMI_CORE_SYS 0x400 43#define HDMI_CORE_SYS 0x400
44#define HDMI_CORE_AV 0x900 44#define HDMI_CORE_AV 0x900
45#define HDMI_PLLCTRL 0x200
46#define HDMI_PHY 0x300 45#define HDMI_PHY 0x300
47 46
48/* HDMI EDID Length move this */ 47/* HDMI EDID Length move this */
@@ -53,9 +52,6 @@
53#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 52#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
54#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 53#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
55 54
56#define HDMI_DEFAULT_REGN 16
57#define HDMI_DEFAULT_REGM2 1
58
59static struct { 55static struct {
60 struct mutex lock; 56 struct mutex lock;
61 struct platform_device *pdev; 57 struct platform_device *pdev;
@@ -428,52 +424,6 @@ end: return cm;
428 424
429} 425}
430 426
431static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
432 struct hdmi_pll_info *pi)
433{
434 unsigned long clkin, refclk;
435 u32 mf;
436
437 clkin = clk_get_rate(hdmi.sys_clk) / 10000;
438 /*
439 * Input clock is predivided by N + 1
440 * out put of which is reference clk
441 */
442
443 pi->regn = HDMI_DEFAULT_REGN;
444
445 refclk = clkin / pi->regn;
446
447 pi->regm2 = HDMI_DEFAULT_REGM2;
448
449 /*
450 * multiplier is pixel_clk/ref_clk
451 * Multiplying by 100 to avoid fractional part removal
452 */
453 pi->regm = phy * pi->regm2 / refclk;
454
455 /*
456 * fractional multiplier is remainder of the difference between
457 * multiplier and actual phy(required pixel clock thus should be
458 * multiplied by 2^18(262144) divided by the reference clock
459 */
460 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
461 pi->regmf = pi->regm2 * mf / refclk;
462
463 /*
464 * Dcofreq should be set to 1 if required pixel clock
465 * is greater than 1000MHz
466 */
467 pi->dcofreq = phy > 1000 * 100;
468 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
469
470 /* Set the reference clock to sysclk reference */
471 pi->refsel = HDMI_REFSEL_SYSCLK;
472
473 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
474 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
475}
476
477static int hdmi_power_on_core(struct omap_dss_device *dssdev) 427static int hdmi_power_on_core(struct omap_dss_device *dssdev)
478{ 428{
479 int r; 429 int r;
@@ -526,12 +476,12 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
526 476
527 phy = p->pixel_clock; 477 phy = p->pixel_clock;
528 478
529 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 479 hdmi_pll_compute(&hdmi.ip_data.pll, clk_get_rate(hdmi.sys_clk), phy);
530 480
531 hdmi_wp_video_stop(&hdmi.ip_data.wp); 481 hdmi_wp_video_stop(&hdmi.ip_data.wp);
532 482
533 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 483 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
534 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 484 r = hdmi_pll_enable(&hdmi.ip_data.pll, &hdmi.ip_data.wp);
535 if (r) { 485 if (r) {
536 DSSDBG("Failed to lock PLL\n"); 486 DSSDBG("Failed to lock PLL\n");
537 goto err_pll_enable; 487 goto err_pll_enable;
@@ -566,7 +516,7 @@ err_mgr_enable:
566err_vid_enable: 516err_vid_enable:
567 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 517 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
568err_phy_enable: 518err_phy_enable:
569 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 519 hdmi_pll_disable(&hdmi.ip_data.pll, &hdmi.ip_data.wp);
570err_pll_enable: 520err_pll_enable:
571 hdmi_power_off_core(dssdev); 521 hdmi_power_off_core(dssdev);
572 return -EIO; 522 return -EIO;
@@ -580,7 +530,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
580 530
581 hdmi_wp_video_stop(&hdmi.ip_data.wp); 531 hdmi_wp_video_stop(&hdmi.ip_data.wp);
582 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 532 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 533 hdmi_pll_disable(&hdmi.ip_data.pll, &hdmi.ip_data.wp);
584 534
585 hdmi_power_off_core(dssdev); 535 hdmi_power_off_core(dssdev);
586} 536}
@@ -642,7 +592,7 @@ static void hdmi_dump_regs(struct seq_file *s)
642 } 592 }
643 593
644 hdmi_wp_dump(&hdmi.ip_data.wp, s); 594 hdmi_wp_dump(&hdmi.ip_data.wp, s);
645 hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); 595 hdmi_pll_dump(&hdmi.ip_data.pll, s);
646 hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); 596 hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
647 hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); 597 hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
648 598
@@ -1095,6 +1045,10 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1095 if (r) 1045 if (r)
1096 return r; 1046 return r;
1097 1047
1048 r = hdmi_pll_init(pdev, &hdmi.ip_data.pll);
1049 if (r)
1050 return r;
1051
1098 hdmi.ip_data.irq = platform_get_irq(pdev, 0); 1052 hdmi.ip_data.irq = platform_get_irq(pdev, 0);
1099 if (hdmi.ip_data.irq < 0) { 1053 if (hdmi.ip_data.irq < 0) {
1100 DSSERR("platform_get_irq failed\n"); 1054 DSSERR("platform_get_irq failed\n");
@@ -1111,7 +1065,6 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1111 1065
1112 hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; 1066 hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS;
1113 hdmi.ip_data.core_av_offset = HDMI_CORE_AV; 1067 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
1114 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1115 hdmi.ip_data.phy_offset = HDMI_PHY; 1068 hdmi.ip_data.phy_offset = HDMI_PHY;
1116 1069
1117 hdmi_init_output(pdev); 1070 hdmi_init_output(pdev);
diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/omap2/dss/hdmi_pll.c
new file mode 100644
index 000000000000..e12fa6ada58f
--- /dev/null
+++ b/drivers/video/omap2/dss/hdmi_pll.c
@@ -0,0 +1,261 @@
1/*
2 * HDMI PLL
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/platform_device.h>
17#include <video/omapdss.h>
18
19#include "dss.h"
20#include "ti_hdmi.h"
21#include "ti_hdmi_4xxx_ip.h"
22
23#define HDMI_DEFAULT_REGN 16
24#define HDMI_DEFAULT_REGM2 1
25
26static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx,
27 u32 val)
28{
29 __raw_writel(val, base_addr + idx);
30}
31
32static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx)
33{
34 return __raw_readl(base_addr + idx);
35}
36
37#define REG_FLD_MOD(base, idx, val, start, end) \
38 hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
39 val, start, end))
40#define REG_GET(base, idx, start, end) \
41 FLD_GET(hdmi_read_reg(base, idx), start, end)
42
43static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
44 const u16 idx, int b2, int b1, u32 val)
45{
46 u32 t = 0;
47 while (val != REG_GET(base_addr, idx, b2, b1)) {
48 udelay(1);
49 if (t++ > 10000)
50 return !val;
51 }
52 return val;
53}
54
55void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
56{
57#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
58 hdmi_read_reg(pll->base, r))
59
60 DUMPPLL(PLLCTRL_PLL_CONTROL);
61 DUMPPLL(PLLCTRL_PLL_STATUS);
62 DUMPPLL(PLLCTRL_PLL_GO);
63 DUMPPLL(PLLCTRL_CFG1);
64 DUMPPLL(PLLCTRL_CFG2);
65 DUMPPLL(PLLCTRL_CFG3);
66 DUMPPLL(PLLCTRL_SSC_CFG1);
67 DUMPPLL(PLLCTRL_SSC_CFG2);
68 DUMPPLL(PLLCTRL_CFG4);
69}
70
71void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy)
72{
73 struct hdmi_pll_info *pi = &pll->info;
74 unsigned long refclk;
75 u32 mf;
76
77 /* use our funky units */
78 clkin /= 10000;
79
80 /*
81 * Input clock is predivided by N + 1
82 * out put of which is reference clk
83 */
84
85 pi->regn = HDMI_DEFAULT_REGN;
86
87 refclk = clkin / pi->regn;
88
89 pi->regm2 = HDMI_DEFAULT_REGM2;
90
91 /*
92 * multiplier is pixel_clk/ref_clk
93 * Multiplying by 100 to avoid fractional part removal
94 */
95 pi->regm = phy * pi->regm2 / refclk;
96
97 /*
98 * fractional multiplier is remainder of the difference between
99 * multiplier and actual phy(required pixel clock thus should be
100 * multiplied by 2^18(262144) divided by the reference clock
101 */
102 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
103 pi->regmf = pi->regm2 * mf / refclk;
104
105 /*
106 * Dcofreq should be set to 1 if required pixel clock
107 * is greater than 1000MHz
108 */
109 pi->dcofreq = phy > 1000 * 100;
110 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
111
112 /* Set the reference clock to sysclk reference */
113 pi->refsel = HDMI_REFSEL_SYSCLK;
114
115 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
116 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
117}
118
119
120static int hdmi_pll_config(struct hdmi_pll_data *pll)
121{
122 u32 r;
123 struct hdmi_pll_info *fmt = &pll->info;
124
125 /* PLL start always use manual mode */
126 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
127
128 r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
129 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
130 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
131 hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
132
133 r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
134
135 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
136 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
137 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
138 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
139
140 if (fmt->dcofreq) {
141 /* divider programming for frequency beyond 1000Mhz */
142 REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
143 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
144 } else {
145 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
146 }
147
148 hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
149
150 r = hdmi_read_reg(pll->base, PLLCTRL_CFG4);
151 r = FLD_MOD(r, fmt->regm2, 24, 18);
152 r = FLD_MOD(r, fmt->regmf, 17, 0);
153 hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
154
155 /* go now */
156 REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
157
158 /* wait for bit change */
159 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO,
160 0, 0, 1) != 1) {
161 pr_err("PLL GO bit not set\n");
162 return -ETIMEDOUT;
163 }
164
165 /* Wait till the lock bit is set in PLL status */
166 if (hdmi_wait_for_bit_change(pll->base,
167 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
168 pr_err("cannot lock PLL\n");
169 pr_err("CFG1 0x%x\n",
170 hdmi_read_reg(pll->base, PLLCTRL_CFG1));
171 pr_err("CFG2 0x%x\n",
172 hdmi_read_reg(pll->base, PLLCTRL_CFG2));
173 pr_err("CFG4 0x%x\n",
174 hdmi_read_reg(pll->base, PLLCTRL_CFG4));
175 return -ETIMEDOUT;
176 }
177
178 pr_debug("PLL locked!\n");
179
180 return 0;
181}
182
183static int hdmi_pll_reset(struct hdmi_pll_data *pll)
184{
185 /* SYSRESET controlled by power FSM */
186 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
187
188 /* READ 0x0 reset is in progress */
189 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
190 != 1) {
191 pr_err("Failed to sysreset PLL\n");
192 return -ETIMEDOUT;
193 }
194
195 return 0;
196}
197
198int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
199{
200 u16 r = 0;
201
202 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
203 if (r)
204 return r;
205
206 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
207 if (r)
208 return r;
209
210 r = hdmi_pll_reset(pll);
211 if (r)
212 return r;
213
214 r = hdmi_pll_config(pll);
215 if (r)
216 return r;
217
218 return 0;
219}
220
221void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
222{
223 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
224}
225
226#define PLL_OFFSET 0x200
227#define PLL_SIZE 0x100
228
229int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
230{
231 struct resource *res;
232 struct resource temp_res;
233
234 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi_pllctrl");
235 if (!res) {
236 DSSDBG("can't get PLL mem resource by name\n");
237 /*
238 * if hwmod/DT doesn't have the memory resource information
239 * split into HDMI sub blocks by name, we try again by getting
240 * the platform's first resource. this code will be removed when
241 * the driver can get the mem resources by name
242 */
243 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
244 if (!res) {
245 DSSERR("can't get PLL mem resource\n");
246 return -EINVAL;
247 }
248
249 temp_res.start = res->start + PLL_OFFSET;
250 temp_res.end = temp_res.start + PLL_SIZE - 1;
251 res = &temp_res;
252 }
253
254 pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
255 if (!pll->base) {
256 DSSERR("can't ioremap PLLCTRL\n");
257 return -ENOMEM;
258 }
259
260 return 0;
261}
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index d16f28de1272..62a83c79628e 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -155,14 +155,8 @@ struct ti_hdmi_ip_ops {
155 155
156 int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); 156 int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
157 157
158 int (*pll_enable)(struct hdmi_ip_data *ip_data);
159
160 void (*pll_disable)(struct hdmi_ip_data *ip_data);
161
162 void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); 158 void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
163 159
164 void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
165
166 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); 160 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
167 161
168#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 162#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
@@ -223,17 +217,22 @@ struct hdmi_wp_data {
223 void __iomem *base; 217 void __iomem *base;
224}; 218};
225 219
220struct hdmi_pll_data {
221 void __iomem *base;
222
223 struct hdmi_pll_info info;
224};
225
226struct hdmi_ip_data { 226struct hdmi_ip_data {
227 struct hdmi_wp_data wp; 227 struct hdmi_wp_data wp;
228 struct hdmi_pll_data pll;
228 229
229 unsigned long core_sys_offset; 230 unsigned long core_sys_offset;
230 unsigned long core_av_offset; 231 unsigned long core_av_offset;
231 unsigned long pll_offset;
232 unsigned long phy_offset; 232 unsigned long phy_offset;
233 int irq; 233 int irq;
234 const struct ti_hdmi_ip_ops *ops; 234 const struct ti_hdmi_ip_ops *ops;
235 struct hdmi_config cfg; 235 struct hdmi_config cfg;
236 struct hdmi_pll_info pll_data;
237 struct hdmi_core_infoframe_avi avi_cfg; 236 struct hdmi_core_infoframe_avi avi_cfg;
238 237
239 /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */ 238 /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
@@ -260,13 +259,17 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
260 struct omap_video_timings *timings, struct hdmi_config *param); 259 struct omap_video_timings *timings, struct hdmi_config *param);
261int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); 260int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
262 261
262/* HDMI PLL funcs */
263int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
264void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
265void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
266void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
267int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
268
263int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); 269int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
264void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); 270void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
265int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); 271int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
266int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
267void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
268void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); 272void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
269void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
270void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 273void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
271void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 274void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
272#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 275#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index d4b8883ecac0..8cfb54b39688 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -75,11 +75,6 @@ static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
75 return ip_data->wp.base + ip_data->phy_offset; 75 return ip_data->wp.base + ip_data->phy_offset;
76} 76}
77 77
78static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
79{
80 return ip_data->wp.base + ip_data->pll_offset;
81}
82
83static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) 78static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
84{ 79{
85 return ip_data->wp.base + ip_data->core_av_offset; 80 return ip_data->wp.base + ip_data->core_av_offset;
@@ -90,117 +85,6 @@ static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
90 return ip_data->wp.base + ip_data->core_sys_offset; 85 return ip_data->wp.base + ip_data->core_sys_offset;
91} 86}
92 87
93
94static int hdmi_pll_init(struct hdmi_ip_data *ip_data)
95{
96 u32 r;
97 void __iomem *pll_base = hdmi_pll_base(ip_data);
98 struct hdmi_pll_info *fmt = &ip_data->pll_data;
99
100 /* PLL start always use manual mode */
101 REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
102
103 r = hdmi_read_reg(pll_base, PLLCTRL_CFG1);
104 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
105 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
106
107 hdmi_write_reg(pll_base, PLLCTRL_CFG1, r);
108
109 r = hdmi_read_reg(pll_base, PLLCTRL_CFG2);
110
111 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
112 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
113 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
114 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
115
116 if (fmt->dcofreq) {
117 /* divider programming for frequency beyond 1000Mhz */
118 REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
119 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
120 } else {
121 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
122 }
123
124 hdmi_write_reg(pll_base, PLLCTRL_CFG2, r);
125
126 r = hdmi_read_reg(pll_base, PLLCTRL_CFG4);
127 r = FLD_MOD(r, fmt->regm2, 24, 18);
128 r = FLD_MOD(r, fmt->regmf, 17, 0);
129
130 hdmi_write_reg(pll_base, PLLCTRL_CFG4, r);
131
132 /* go now */
133 REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0);
134
135 /* wait for bit change */
136 if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO,
137 0, 0, 1) != 1) {
138 pr_err("PLL GO bit not set\n");
139 return -ETIMEDOUT;
140 }
141
142 /* Wait till the lock bit is set in PLL status */
143 if (hdmi_wait_for_bit_change(pll_base,
144 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
145 pr_err("cannot lock PLL\n");
146 pr_err("CFG1 0x%x\n",
147 hdmi_read_reg(pll_base, PLLCTRL_CFG1));
148 pr_err("CFG2 0x%x\n",
149 hdmi_read_reg(pll_base, PLLCTRL_CFG2));
150 pr_err("CFG4 0x%x\n",
151 hdmi_read_reg(pll_base, PLLCTRL_CFG4));
152 return -ETIMEDOUT;
153 }
154
155 pr_debug("PLL locked!\n");
156
157 return 0;
158}
159
160
161static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
162{
163 /* SYSRESET controlled by power FSM */
164 REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
165
166 /* READ 0x0 reset is in progress */
167 if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
168 PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
169 pr_err("Failed to sysreset PLL\n");
170 return -ETIMEDOUT;
171 }
172
173 return 0;
174}
175
176int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data)
177{
178 u16 r = 0;
179
180 r = hdmi_wp_set_pll_pwr(&ip_data->wp, HDMI_PLLPWRCMD_ALLOFF);
181 if (r)
182 return r;
183
184 r = hdmi_wp_set_pll_pwr(&ip_data->wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
185 if (r)
186 return r;
187
188 r = hdmi_pll_reset(ip_data);
189 if (r)
190 return r;
191
192 r = hdmi_pll_init(ip_data);
193 if (r)
194 return r;
195
196 return 0;
197}
198
199void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
200{
201 hdmi_wp_set_pll_pwr(&ip_data->wp, HDMI_PLLPWRCMD_ALLOFF);
202}
203
204static irqreturn_t hdmi_irq_handler(int irq, void *data) 88static irqreturn_t hdmi_irq_handler(int irq, void *data)
205{ 89{
206 struct hdmi_ip_data *ip_data = data; 90 struct hdmi_ip_data *ip_data = data;
@@ -717,22 +601,6 @@ void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
717 hdmi_core_av_packet_config(ip_data, repeat_cfg); 601 hdmi_core_av_packet_config(ip_data, repeat_cfg);
718} 602}
719 603
720void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
721{
722#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
723 hdmi_read_reg(hdmi_pll_base(ip_data), r))
724
725 DUMPPLL(PLLCTRL_PLL_CONTROL);
726 DUMPPLL(PLLCTRL_PLL_STATUS);
727 DUMPPLL(PLLCTRL_PLL_GO);
728 DUMPPLL(PLLCTRL_CFG1);
729 DUMPPLL(PLLCTRL_CFG2);
730 DUMPPLL(PLLCTRL_CFG3);
731 DUMPPLL(PLLCTRL_SSC_CFG1);
732 DUMPPLL(PLLCTRL_SSC_CFG2);
733 DUMPPLL(PLLCTRL_CFG4);
734}
735
736void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) 604void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
737{ 605{
738 int i; 606 int i;