aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/omap2
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2013-10-28 05:47:34 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-05-09 08:11:28 -0400
commitdcf5f7299e94d113aa49b4e099c4b9f289d17ed2 (patch)
treed1e223c90de42595a98f138ef8a2819449d1a463 /drivers/video/fbdev/omap2
parent543e761fb9c128d9065f45697cd96d04a566d2ce (diff)
OMAPDSS: HDMI: move irq & phy pwr handling
HDMI IRQ handling was moved into hdmi_phy.c when restructuring the HDMI driver. While this worked fine, it's not correct. The HDMI IRQ handling should be either in the hdmi_wp, or in the main hdmi driver. This patch moves the handling to the main hdmi driver, as I feel it's a more appropriate choice. This move also requires changing the handling of the PHY power, as that was partly handled in the IRQ handler. The PHY power is handled via the WP module. An option would be to give HDMI PHY driver function pointers that it could use to manage the PHY power, but as the PHY power is not needed to access the PHY registers, the handling was also moved to the main HDMI driver. This could be changed later if need be. Note that there's slightly similar power issue with the PLL: the HDMI PLLs power is also handled via the WP module. For now, the PLL power handling is still done inside the PLL driver. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/fbdev/omap2')
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h6
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c75
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_phy.c70
3 files changed, 71 insertions, 80 deletions
diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
index 4e5c44e7eeb3..d784b2cced9d 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
@@ -351,8 +351,6 @@ struct hdmi_pll_data {
351struct hdmi_phy_data { 351struct hdmi_phy_data {
352 void __iomem *base; 352 void __iomem *base;
353 353
354 int irq;
355
356 u8 lane_function[4]; 354 u8 lane_function[4];
357 u8 lane_polarity[4]; 355 u8 lane_polarity[4];
358}; 356};
@@ -420,9 +418,7 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
420int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); 418int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
421 419
422/* HDMI PHY funcs */ 420/* HDMI PHY funcs */
423int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, 421int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg);
424 struct hdmi_config *cfg);
425void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
426void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); 422void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
427int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); 423int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
428int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes); 424int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
index 5c7dd5c06593..626aad2bef46 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -81,6 +81,37 @@ static void hdmi_runtime_put(void)
81 WARN_ON(r < 0 && r != -ENOSYS); 81 WARN_ON(r < 0 && r != -ENOSYS);
82} 82}
83 83
84static irqreturn_t hdmi_irq_handler(int irq, void *data)
85{
86 struct hdmi_wp_data *wp = data;
87 u32 irqstatus;
88
89 irqstatus = hdmi_wp_get_irqstatus(wp);
90 hdmi_wp_set_irqstatus(wp, irqstatus);
91
92 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
93 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
94 /*
95 * If we get both connect and disconnect interrupts at the same
96 * time, turn off the PHY, clear interrupts, and restart, which
97 * raises connect interrupt if a cable is connected, or nothing
98 * if cable is not connected.
99 */
100 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
101
102 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
103 HDMI_IRQ_LINK_DISCONNECT);
104
105 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
106 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
107 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
108 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
109 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
110 }
111
112 return IRQ_HANDLED;
113}
114
84static int hdmi_init_regulator(void) 115static int hdmi_init_regulator(void)
85{ 116{
86 int r; 117 int r;
@@ -150,11 +181,16 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
150 struct omap_video_timings *p; 181 struct omap_video_timings *p;
151 struct omap_overlay_manager *mgr = hdmi.output.manager; 182 struct omap_overlay_manager *mgr = hdmi.output.manager;
152 unsigned long phy; 183 unsigned long phy;
184 struct hdmi_wp_data *wp = &hdmi.wp;
153 185
154 r = hdmi_power_on_core(dssdev); 186 r = hdmi_power_on_core(dssdev);
155 if (r) 187 if (r)
156 return r; 188 return r;
157 189
190 /* disable and clear irqs */
191 hdmi_wp_clear_irqenable(wp, 0xffffffff);
192 hdmi_wp_set_irqstatus(wp, 0xffffffff);
193
158 p = &hdmi.cfg.timings; 194 p = &hdmi.cfg.timings;
159 195
160 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 196 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
@@ -171,12 +207,16 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
171 goto err_pll_enable; 207 goto err_pll_enable;
172 } 208 }
173 209
174 r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg); 210 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
175 if (r) { 211 if (r) {
176 DSSDBG("Failed to start PHY\n"); 212 DSSDBG("Failed to configure PHY\n");
177 goto err_phy_enable; 213 goto err_phy_cfg;
178 } 214 }
179 215
216 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
217 if (r)
218 goto err_phy_pwr;
219
180 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); 220 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
181 221
182 /* bypass TV gamma table */ 222 /* bypass TV gamma table */
@@ -193,13 +233,17 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
193 if (r) 233 if (r)
194 goto err_mgr_enable; 234 goto err_mgr_enable;
195 235
236 hdmi_wp_set_irqenable(wp,
237 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
238
196 return 0; 239 return 0;
197 240
198err_mgr_enable: 241err_mgr_enable:
199 hdmi_wp_video_stop(&hdmi.wp); 242 hdmi_wp_video_stop(&hdmi.wp);
200err_vid_enable: 243err_vid_enable:
201 hdmi_phy_disable(&hdmi.phy, &hdmi.wp); 244err_phy_cfg:
202err_phy_enable: 245 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
246err_phy_pwr:
203 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 247 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
204err_pll_enable: 248err_pll_enable:
205 hdmi_power_off_core(dssdev); 249 hdmi_power_off_core(dssdev);
@@ -210,10 +254,14 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
210{ 254{
211 struct omap_overlay_manager *mgr = hdmi.output.manager; 255 struct omap_overlay_manager *mgr = hdmi.output.manager;
212 256
257 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
258
213 dss_mgr_disable(mgr); 259 dss_mgr_disable(mgr);
214 260
215 hdmi_wp_video_stop(&hdmi.wp); 261 hdmi_wp_video_stop(&hdmi.wp);
216 hdmi_phy_disable(&hdmi.phy, &hdmi.wp); 262
263 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
264
217 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 265 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
218 266
219 hdmi_power_off_core(dssdev); 267 hdmi_power_off_core(dssdev);
@@ -636,6 +684,7 @@ err:
636static int omapdss_hdmihw_probe(struct platform_device *pdev) 684static int omapdss_hdmihw_probe(struct platform_device *pdev)
637{ 685{
638 int r; 686 int r;
687 int irq;
639 688
640 hdmi.pdev = pdev; 689 hdmi.pdev = pdev;
641 690
@@ -669,6 +718,20 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
669 return r; 718 return r;
670 } 719 }
671 720
721 irq = platform_get_irq(pdev, 0);
722 if (irq < 0) {
723 DSSERR("platform_get_irq failed\n");
724 return -ENODEV;
725 }
726
727 r = devm_request_threaded_irq(&pdev->dev, irq,
728 NULL, hdmi_irq_handler,
729 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
730 if (r) {
731 DSSERR("HDMI IRQ request failed\n");
732 return r;
733 }
734
672 pm_runtime_enable(&pdev->dev); 735 pm_runtime_enable(&pdev->dev);
673 736
674 hdmi_init_output(pdev); 737 hdmi_init_output(pdev);
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
index c1c65624fd5d..8d13e422de5e 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_phy.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
@@ -28,37 +28,6 @@ void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
28 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); 28 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
29} 29}
30 30
31static irqreturn_t hdmi_irq_handler(int irq, void *data)
32{
33 struct hdmi_wp_data *wp = data;
34 u32 irqstatus;
35
36 irqstatus = hdmi_wp_get_irqstatus(wp);
37 hdmi_wp_set_irqstatus(wp, irqstatus);
38
39 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
40 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
41 /*
42 * If we get both connect and disconnect interrupts at the same
43 * time, turn off the PHY, clear interrupts, and restart, which
44 * raises connect interrupt if a cable is connected, or nothing
45 * if cable is not connected.
46 */
47 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
48
49 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
50 HDMI_IRQ_LINK_DISCONNECT);
51
52 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
53 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
54 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
55 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
56 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
57 }
58
59 return IRQ_HANDLED;
60}
61
62int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes) 31int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes)
63{ 32{
64 int i; 33 int i;
@@ -150,21 +119,8 @@ static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
150 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27); 119 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
151} 120}
152 121
153int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, 122int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
154 struct hdmi_config *cfg)
155{ 123{
156 u16 r = 0;
157 u32 irqstatus;
158
159 hdmi_wp_clear_irqenable(wp, 0xffffffff);
160
161 irqstatus = hdmi_wp_get_irqstatus(wp);
162 hdmi_wp_set_irqstatus(wp, irqstatus);
163
164 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
165 if (r)
166 return r;
167
168 /* 124 /*
169 * Read address 0 in order to get the SCP reset done completed 125 * Read address 0 in order to get the SCP reset done completed
170 * Dummy access performed to make sure reset is done 126 * Dummy access performed to make sure reset is done
@@ -185,27 +141,9 @@ int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
185 141
186 hdmi_phy_configure_lanes(phy); 142 hdmi_phy_configure_lanes(phy);
187 143
188 r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler,
189 IRQF_ONESHOT, "OMAP HDMI", wp);
190 if (r) {
191 DSSERR("HDMI IRQ request failed\n");
192 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
193 return r;
194 }
195
196 hdmi_wp_set_irqenable(wp,
197 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
198
199 return 0; 144 return 0;
200} 145}
201 146
202void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp)
203{
204 free_irq(phy->irq, wp);
205
206 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
207}
208
209#define PHY_OFFSET 0x300 147#define PHY_OFFSET 0x300
210#define PHY_SIZE 0x100 148#define PHY_SIZE 0x100
211 149
@@ -240,11 +178,5 @@ int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
240 return -ENOMEM; 178 return -ENOMEM;
241 } 179 }
242 180
243 phy->irq = platform_get_irq(pdev, 0);
244 if (phy->irq < 0) {
245 DSSERR("platform_get_irq failed\n");
246 return -ENODEV;
247 }
248
249 return 0; 181 return 0;
250} 182}