diff options
-rw-r--r-- | drivers/video/omap2/dss/hdmi.c | 6 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi.h | 1 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | 81 | ||||
-rw-r--r-- | drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | 1 |
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 | |||
41 | static inline void hdmi_write_reg(void __iomem *base_addr, | 44 | static 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 | ||
236 | static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data) | 239 | static 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 | ||
256 | err: | ||
257 | mutex_unlock(&ip_data->lock); | ||
258 | return r; | ||
259 | } | ||
260 | |||
261 | static 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 | ||
320 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) | 325 | void 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 |