diff options
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi.h | 6 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi4.c | 75 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/dss/hdmi_phy.c | 70 |
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 { struct hdmi_phy_data { void __iomem *base; - int irq; - u8 lane_function[4]; u8 lane_polarity[4]; }; @@ -420,9 +418,7 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy); int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); /* HDMI PHY funcs */ -int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, - struct hdmi_config *cfg); -void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp); +int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg); void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); int 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) WARN_ON(r < 0 && r != -ENOSYS); } +static irqreturn_t hdmi_irq_handler(int irq, void *data) +{ + struct hdmi_wp_data *wp = data; + u32 irqstatus; + + irqstatus = hdmi_wp_get_irqstatus(wp); + hdmi_wp_set_irqstatus(wp, irqstatus); + + if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && + irqstatus & HDMI_IRQ_LINK_DISCONNECT) { + /* + * If we get both connect and disconnect interrupts at the same + * time, turn off the PHY, clear interrupts, and restart, which + * raises connect interrupt if a cable is connected, or nothing + * if cable is not connected. + */ + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); + + hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | + HDMI_IRQ_LINK_DISCONNECT); + + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); + } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { + hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + } + + return IRQ_HANDLED; +} + static int hdmi_init_regulator(void) { int r; @@ -150,11 +181,16 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) struct omap_video_timings *p; struct omap_overlay_manager *mgr = hdmi.output.manager; unsigned long phy; + struct hdmi_wp_data *wp = &hdmi.wp; r = hdmi_power_on_core(dssdev); if (r) return r; + /* disable and clear irqs */ + hdmi_wp_clear_irqenable(wp, 0xffffffff); + hdmi_wp_set_irqstatus(wp, 0xffffffff); + p = &hdmi.cfg.timings; 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) goto err_pll_enable; } - r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg); + r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg); if (r) { - DSSDBG("Failed to start PHY\n"); - goto err_phy_enable; + DSSDBG("Failed to configure PHY\n"); + goto err_phy_cfg; } + r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); + if (r) + goto err_phy_pwr; + hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); /* bypass TV gamma table */ @@ -193,13 +233,17 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) if (r) goto err_mgr_enable; + hdmi_wp_set_irqenable(wp, + HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); + return 0; err_mgr_enable: hdmi_wp_video_stop(&hdmi.wp); err_vid_enable: - hdmi_phy_disable(&hdmi.phy, &hdmi.wp); -err_phy_enable: +err_phy_cfg: + hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); +err_phy_pwr: hdmi_pll_disable(&hdmi.pll, &hdmi.wp); err_pll_enable: hdmi_power_off_core(dssdev); @@ -210,10 +254,14 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) { struct omap_overlay_manager *mgr = hdmi.output.manager; + hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); + dss_mgr_disable(mgr); hdmi_wp_video_stop(&hdmi.wp); - hdmi_phy_disable(&hdmi.phy, &hdmi.wp); + + hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); + hdmi_pll_disable(&hdmi.pll, &hdmi.wp); hdmi_power_off_core(dssdev); @@ -636,6 +684,7 @@ err: static int omapdss_hdmihw_probe(struct platform_device *pdev) { int r; + int irq; hdmi.pdev = pdev; @@ -669,6 +718,20 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) return r; } + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + DSSERR("platform_get_irq failed\n"); + return -ENODEV; + } + + r = devm_request_threaded_irq(&pdev->dev, irq, + NULL, hdmi_irq_handler, + IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); + if (r) { + DSSERR("HDMI IRQ request failed\n"); + return r; + } + pm_runtime_enable(&pdev->dev); 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) DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); } -static irqreturn_t hdmi_irq_handler(int irq, void *data) -{ - struct hdmi_wp_data *wp = data; - u32 irqstatus; - - irqstatus = hdmi_wp_get_irqstatus(wp); - hdmi_wp_set_irqstatus(wp, irqstatus); - - if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && - irqstatus & HDMI_IRQ_LINK_DISCONNECT) { - /* - * If we get both connect and disconnect interrupts at the same - * time, turn off the PHY, clear interrupts, and restart, which - * raises connect interrupt if a cable is connected, or nothing - * if cable is not connected. - */ - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); - - hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | - HDMI_IRQ_LINK_DISCONNECT); - - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); - } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); - } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); - } - - return IRQ_HANDLED; -} - int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes) { int i; @@ -150,21 +119,8 @@ static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy) REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27); } -int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, - struct hdmi_config *cfg) +int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg) { - u16 r = 0; - u32 irqstatus; - - hdmi_wp_clear_irqenable(wp, 0xffffffff); - - irqstatus = hdmi_wp_get_irqstatus(wp); - hdmi_wp_set_irqstatus(wp, irqstatus); - - r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); - if (r) - return r; - /* * Read address 0 in order to get the SCP reset done completed * 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, hdmi_phy_configure_lanes(phy); - r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler, - IRQF_ONESHOT, "OMAP HDMI", wp); - if (r) { - DSSERR("HDMI IRQ request failed\n"); - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); - return r; - } - - hdmi_wp_set_irqenable(wp, - HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT); - return 0; } -void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp) -{ - free_irq(phy->irq, wp); - - hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); -} - #define PHY_OFFSET 0x300 #define PHY_SIZE 0x100 @@ -240,11 +178,5 @@ int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) return -ENOMEM; } - phy->irq = platform_get_irq(pdev, 0); - if (phy->irq < 0) { - DSSERR("platform_get_irq failed\n"); - return -ENODEV; - } - return 0; } |