|
@@ -32,6 +32,7 @@
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/pm_runtime.h>
|
|
|
#include <linux/clk.h>
|
|
|
+#include <linux/gpio.h>
|
|
|
#include <video/omapdss.h>
|
|
|
|
|
|
#include "ti_hdmi.h"
|
|
@@ -61,6 +62,10 @@ static struct {
|
|
|
struct hdmi_ip_data ip_data;
|
|
|
|
|
|
struct clk *sys_clk;
|
|
|
+
|
|
|
+ int ct_cp_hpd_gpio;
|
|
|
+ int ls_oe_gpio;
|
|
|
+ int hpd_gpio;
|
|
|
} hdmi;
|
|
|
|
|
|
/*
|
|
@@ -314,12 +319,34 @@ static void hdmi_runtime_put(void)
|
|
|
|
|
|
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
|
|
{
|
|
|
+ int r;
|
|
|
+
|
|
|
+ struct gpio gpios[] = {
|
|
|
+ { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
|
|
|
+ { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
|
|
|
+ { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
|
|
|
+ };
|
|
|
+
|
|
|
DSSDBG("init_display\n");
|
|
|
|
|
|
dss_init_hdmi_ip_ops(&hdmi.ip_data);
|
|
|
+
|
|
|
+ r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
|
|
|
+{
|
|
|
+ DSSDBG("uninit_display\n");
|
|
|
+
|
|
|
+ gpio_free(hdmi.ct_cp_hpd_gpio);
|
|
|
+ gpio_free(hdmi.ls_oe_gpio);
|
|
|
+ gpio_free(hdmi.hpd_gpio);
|
|
|
+}
|
|
|
+
|
|
|
static const struct hdmi_config *hdmi_find_timing(
|
|
|
const struct hdmi_config *timings_arr,
|
|
|
int len)
|
|
@@ -462,9 +489,12 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|
|
struct omap_video_timings *p;
|
|
|
unsigned long phy;
|
|
|
|
|
|
+ gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
|
|
|
+ gpio_set_value(hdmi.ls_oe_gpio, 1);
|
|
|
+
|
|
|
r = hdmi_runtime_get();
|
|
|
if (r)
|
|
|
- return r;
|
|
|
+ goto err_runtime_get;
|
|
|
|
|
|
dss_mgr_disable(dssdev->manager);
|
|
|
|
|
@@ -482,7 +512,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|
|
r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
|
|
|
if (r) {
|
|
|
DSSDBG("Failed to lock PLL\n");
|
|
|
- goto err;
|
|
|
+ goto err_pll_enable;
|
|
|
}
|
|
|
|
|
|
r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
|
|
@@ -526,8 +556,11 @@ err_vid_enable:
|
|
|
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
|
|
err_phy_enable:
|
|
|
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
|
|
-err:
|
|
|
+err_pll_enable:
|
|
|
hdmi_runtime_put();
|
|
|
+err_runtime_get:
|
|
|
+ gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
|
|
+ gpio_set_value(hdmi.ls_oe_gpio, 0);
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
@@ -539,6 +572,9 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
|
|
|
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
|
|
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
|
|
hdmi_runtime_put();
|
|
|
+
|
|
|
+ gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
|
|
|
+ gpio_set_value(hdmi.ls_oe_gpio, 0);
|
|
|
}
|
|
|
|
|
|
int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
|
|
@@ -637,7 +673,6 @@ bool omapdss_hdmi_detect(void)
|
|
|
|
|
|
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|
|
{
|
|
|
- struct omap_dss_hdmi_data *priv = dssdev->data;
|
|
|
int r = 0;
|
|
|
|
|
|
DSSDBG("ENTER hdmi_display_enable\n");
|
|
@@ -650,7 +685,7 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|
|
goto err0;
|
|
|
}
|
|
|
|
|
|
- hdmi.ip_data.hpd_gpio = priv->hpd_gpio;
|
|
|
+ hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
|
|
|
|
|
|
r = omap_dss_start_device(dssdev);
|
|
|
if (r) {
|
|
@@ -658,26 +693,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
|
|
|
goto err0;
|
|
|
}
|
|
|
|
|
|
- if (dssdev->platform_enable) {
|
|
|
- r = dssdev->platform_enable(dssdev);
|
|
|
- if (r) {
|
|
|
- DSSERR("failed to enable GPIO's\n");
|
|
|
- goto err1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
r = hdmi_power_on(dssdev);
|
|
|
if (r) {
|
|
|
DSSERR("failed to power on device\n");
|
|
|
- goto err2;
|
|
|
+ goto err1;
|
|
|
}
|
|
|
|
|
|
mutex_unlock(&hdmi.lock);
|
|
|
return 0;
|
|
|
|
|
|
-err2:
|
|
|
- if (dssdev->platform_disable)
|
|
|
- dssdev->platform_disable(dssdev);
|
|
|
err1:
|
|
|
omap_dss_stop_device(dssdev);
|
|
|
err0:
|
|
@@ -693,9 +717,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
|
|
|
|
|
|
hdmi_power_off(dssdev);
|
|
|
|
|
|
- if (dssdev->platform_disable)
|
|
|
- dssdev->platform_disable(dssdev);
|
|
|
-
|
|
|
omap_dss_stop_device(dssdev);
|
|
|
|
|
|
mutex_unlock(&hdmi.lock);
|
|
@@ -873,10 +894,15 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
|
|
|
|
|
for (i = 0; i < pdata->num_devices; ++i) {
|
|
|
struct omap_dss_device *dssdev = pdata->devices[i];
|
|
|
+ struct omap_dss_hdmi_data *priv = dssdev->data;
|
|
|
|
|
|
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
|
|
|
continue;
|
|
|
|
|
|
+ hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
|
|
|
+ hdmi.ls_oe_gpio = priv->ls_oe_gpio;
|
|
|
+ hdmi.hpd_gpio = priv->hpd_gpio;
|
|
|
+
|
|
|
r = hdmi_init_display(dssdev);
|
|
|
if (r) {
|
|
|
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
|
@@ -938,8 +964,17 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int __exit hdmi_remove_child(struct device *dev, void *data)
|
|
|
+{
|
|
|
+ struct omap_dss_device *dssdev = to_dss_device(dev);
|
|
|
+ hdmi_uninit_display(dssdev);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
+ device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
|
|
|
+
|
|
|
omap_dss_unregister_child_devices(&pdev->dev);
|
|
|
|
|
|
hdmi_panel_exit();
|