aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/omap2/dss/hdmi.c6
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h1
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c81
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h1
4 files changed, 51 insertions, 38 deletions
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 0f93903d4409..0fb3662e28b6 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -1072,6 +1072,12 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
1072 if (IS_ERR(hdmi.ip_data.base_wp)) 1072 if (IS_ERR(hdmi.ip_data.base_wp))
1073 return PTR_ERR(hdmi.ip_data.base_wp); 1073 return PTR_ERR(hdmi.ip_data.base_wp);
1074 1074
1075 hdmi.ip_data.irq = platform_get_irq(pdev, 0);
1076 if (hdmi.ip_data.irq < 0) {
1077 DSSERR("platform_get_irq failed\n");
1078 return -ENODEV;
1079 }
1080
1075 r = hdmi_get_clocks(pdev); 1081 r = hdmi_get_clocks(pdev);
1076 if (r) { 1082 if (r) {
1077 DSSERR("can't get clocks\n"); 1083 DSSERR("can't get clocks\n");
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 216aa704f9d7..2f7fbc894578 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -155,6 +155,7 @@ struct hdmi_ip_data {
155 unsigned long core_av_offset; 155 unsigned long core_av_offset;
156 unsigned long pll_offset; 156 unsigned long pll_offset;
157 unsigned long phy_offset; 157 unsigned long phy_offset;
158 int irq;
158 const struct ti_hdmi_ip_ops *ops; 159 const struct ti_hdmi_ip_ops *ops;
159 struct hdmi_config cfg; 160 struct hdmi_config cfg;
160 struct hdmi_pll_info pll_data; 161 struct hdmi_pll_info pll_data;
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index e18b222ed739..052f2db35d62 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -38,6 +38,9 @@
38#include "dss.h" 38#include "dss.h"
39#include "dss_features.h" 39#include "dss_features.h"
40 40
41#define HDMI_IRQ_LINK_CONNECT (1 << 25)
42#define HDMI_IRQ_LINK_DISCONNECT (1 << 26)
43
41static inline void hdmi_write_reg(void __iomem *base_addr, 44static inline void hdmi_write_reg(void __iomem *base_addr,
42 const u16 idx, u32 val) 45 const u16 idx, u32 val)
43{ 46{
@@ -233,37 +236,39 @@ void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
233 hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); 236 hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
234} 237}
235 238
236static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data) 239static irqreturn_t hdmi_irq_handler(int irq, void *data)
237{ 240{
238 bool hpd; 241 struct hdmi_ip_data *ip_data = data;
239 int r; 242 void __iomem *wp_base = hdmi_wp_base(ip_data);
240 243 u32 irqstatus;
241 mutex_lock(&ip_data->lock); 244
242 245 irqstatus = hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
243 hpd = gpio_get_value(ip_data->hpd_gpio); 246 hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS, irqstatus);
247 /* flush posted write */
248 hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
249
250 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
251 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
252 /*
253 * If we get both connect and disconnect interrupts at the same
254 * time, turn off the PHY, clear interrupts, and restart, which
255 * raises connect interrupt if a cable is connected, or nothing
256 * if cable is not connected.
257 */
258 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
244 259
245 if (hpd) 260 hdmi_write_reg(wp_base, HDMI_WP_IRQSTATUS,
246 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); 261 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
247 else 262 /* flush posted write */
248 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); 263 hdmi_read_reg(wp_base, HDMI_WP_IRQSTATUS);
249 264
250 if (r) { 265 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
251 DSSERR("Failed to %s PHY TX power\n", 266 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
252 hpd ? "enable" : "disable"); 267 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
253 goto err; 268 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
269 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
254 } 270 }
255 271
256err:
257 mutex_unlock(&ip_data->lock);
258 return r;
259}
260
261static irqreturn_t hpd_irq_handler(int irq, void *data)
262{
263 struct hdmi_ip_data *ip_data = data;
264
265 hdmi_check_hpd_state(ip_data);
266
267 return IRQ_HANDLED; 272 return IRQ_HANDLED;
268} 273}
269 274
@@ -272,6 +277,12 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
272 u16 r = 0; 277 u16 r = 0;
273 void __iomem *phy_base = hdmi_phy_base(ip_data); 278 void __iomem *phy_base = hdmi_phy_base(ip_data);
274 279
280 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_CLR,
281 0xffffffff);
282
283 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQSTATUS,
284 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
285
275 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); 286 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
276 if (r) 287 if (r)
277 return r; 288 return r;
@@ -297,29 +308,23 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
297 /* Write to phy address 3 to change the polarity control */ 308 /* Write to phy address 3 to change the polarity control */
298 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); 309 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
299 310
300 r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), 311 r = request_threaded_irq(ip_data->irq, NULL, hdmi_irq_handler,
301 NULL, hpd_irq_handler, 312 IRQF_ONESHOT, "OMAP HDMI", ip_data);
302 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
303 IRQF_ONESHOT, "hpd", ip_data);
304 if (r) { 313 if (r) {
305 DSSERR("HPD IRQ request failed\n"); 314 DSSERR("HDMI IRQ request failed\n");
306 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); 315 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
307 return r; 316 return r;
308 } 317 }
309 318
310 r = hdmi_check_hpd_state(ip_data); 319 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_IRQENABLE_SET,
311 if (r) { 320 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
312 free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
313 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
314 return r;
315 }
316 321
317 return 0; 322 return 0;
318} 323}
319 324
320void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) 325void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
321{ 326{
322 free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data); 327 free_irq(ip_data->irq, ip_data);
323 328
324 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); 329 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
325} 330}
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index 8366ae19e82e..6ef2f929a76d 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -33,6 +33,7 @@
33#define HDMI_WP_IRQSTATUS 0x28 33#define HDMI_WP_IRQSTATUS 0x28
34#define HDMI_WP_PWR_CTRL 0x40 34#define HDMI_WP_PWR_CTRL 0x40
35#define HDMI_WP_IRQENABLE_SET 0x2C 35#define HDMI_WP_IRQENABLE_SET 0x2C
36#define HDMI_WP_IRQENABLE_CLR 0x30
36#define HDMI_WP_VIDEO_CFG 0x50 37#define HDMI_WP_VIDEO_CFG 0x50
37#define HDMI_WP_VIDEO_SIZE 0x60 38#define HDMI_WP_VIDEO_SIZE 0x60
38#define HDMI_WP_VIDEO_TIMING_H 0x68 39#define HDMI_WP_VIDEO_TIMING_H 0x68