mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
drm/rockchip: cdn-dp: support get hpd by gpio
DPTX may use tcphy0 or tcphy1. If hardware design support
both tcphy0 and tcphy1, then each phy port need a hpd line.
For example, tcphy0 port use GPIO1B5 and tcphy1 port use
GPIO1B6, it should config dts as follow:
&cdn_dp {
...
pinctrl-names = "default";
pinctrl-0 = <&cnd_dp_hpd>;
hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>,
<&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
phys = <&tcphy0_dp>, <&tcphy1_dp>;
...
};
&pinctrl {
...
dp {
cdn_dp_hpd: cdn-dp-hpd {
rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>,
<1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
...
};
If only 1 phy port can be used for DPTX, For example, using
tcphy0 and GPIO1B5 as hpd pin. It should config dts as follow:
&cdn_dp {
...
pinctrl-names = "default";
pinctrl-0 = <&cnd_dp_hpd>;
hpd-gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_HIGH>;
phys = <&tcphy0_dp>;
...
};
&pinctrl {
...
dp {
cdn_dp_hpd: cdn-dp-hpd {
rockchip,pins = <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
...
};
Change-Id: Id1acc428431bb13d7074e9daaab2fcca2ac2782e
Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
This commit is contained in:
@@ -6,7 +6,9 @@
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -150,6 +152,9 @@ static void cdn_dp_clk_disable(struct cdn_dp_device *dp)
|
||||
|
||||
static int cdn_dp_get_port_lanes(struct cdn_dp_port *port)
|
||||
{
|
||||
if (port->hpd_gpio && !gpiod_get_value_cansleep(port->hpd_gpio))
|
||||
return 0;
|
||||
|
||||
return phy_get_bus_width(port->phy);
|
||||
}
|
||||
|
||||
@@ -776,6 +781,15 @@ static const struct drm_encoder_helper_funcs cdn_dp_encoder_helper_funcs = {
|
||||
static int cdn_dp_encoder_late_register(struct drm_encoder *encoder)
|
||||
{
|
||||
struct cdn_dp_device *dp = encoder_to_dp(encoder);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dp->ports; i++) {
|
||||
if (!dp->port[i])
|
||||
continue;
|
||||
|
||||
if (dp->port[i]->hpd_gpio)
|
||||
enable_irq(dp->port[i]->hpd_irq);
|
||||
}
|
||||
|
||||
dp->registered = true;
|
||||
schedule_delayed_work(&dp->event_work, 0);
|
||||
@@ -786,6 +800,15 @@ static int cdn_dp_encoder_late_register(struct drm_encoder *encoder)
|
||||
static void cdn_dp_encoder_early_unregister(struct drm_encoder *encoder)
|
||||
{
|
||||
struct cdn_dp_device *dp = encoder_to_dp(encoder);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dp->ports; i++) {
|
||||
if (!dp->port[i])
|
||||
continue;
|
||||
|
||||
if (dp->port[i]->hpd_gpio)
|
||||
disable_irq(dp->port[i]->hpd_irq);
|
||||
}
|
||||
|
||||
dp->registered = false;
|
||||
barrier();
|
||||
@@ -1033,6 +1056,16 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t cdn_dp_hpd_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct cdn_dp_port *port = arg;
|
||||
struct cdn_dp_device *dp = port->dp;
|
||||
|
||||
schedule_delayed_work(&dp->event_work, 0);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void cdn_dp_pd_event_work(struct work_struct *work)
|
||||
{
|
||||
struct cdn_dp_device *dp = container_of(to_delayed_work(work), struct cdn_dp_device,
|
||||
@@ -1309,6 +1342,36 @@ static int cdn_dp_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dp->ports; i++) {
|
||||
if (!dp->port[i])
|
||||
continue;
|
||||
|
||||
port = dp->port[i];
|
||||
port->hpd_gpio = devm_gpiod_get_index_optional(dev, "hpd", i, GPIOD_IN);
|
||||
if (IS_ERR(port->hpd_gpio)) {
|
||||
DRM_DEV_ERROR(dev, "failed to get port%d hpd gpio\n", i);
|
||||
return PTR_ERR(port->hpd_gpio);
|
||||
}
|
||||
|
||||
if (port->hpd_gpio) {
|
||||
port->hpd_irq = gpiod_to_irq(port->hpd_gpio);
|
||||
|
||||
if (port->hpd_irq < 0) {
|
||||
DRM_DEV_ERROR(dev, "failed to get port%d hpd irq\n", i);
|
||||
return port->hpd_irq;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, port->hpd_irq, cdn_dp_hpd_irq_handler,
|
||||
IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_NO_AUTOEN, "cdn-dp-hpd", port);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "failed to request HPD interrupt\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_init(&dp->lock);
|
||||
dev_set_drvdata(dev, dp);
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ struct cdn_dp_port {
|
||||
u8 lanes;
|
||||
bool phy_enabled;
|
||||
u8 id;
|
||||
|
||||
struct gpio_desc *hpd_gpio;
|
||||
int hpd_irq;
|
||||
};
|
||||
|
||||
struct cdn_dp_device {
|
||||
|
||||
Reference in New Issue
Block a user