diff options
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_dsi.c | 98 |
1 files changed, 96 insertions, 2 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 58bfb2a2a19b..a19107af1c3b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c | |||
@@ -16,7 +16,9 @@ | |||
16 | #include <drm/drm_panel.h> | 16 | #include <drm/drm_panel.h> |
17 | 17 | ||
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/gpio/consumer.h> | ||
19 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/of_gpio.h> | ||
20 | #include <linux/phy/phy.h> | 22 | #include <linux/phy/phy.h> |
21 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
22 | #include <linux/component.h> | 24 | #include <linux/component.h> |
@@ -24,6 +26,7 @@ | |||
24 | #include <video/mipi_display.h> | 26 | #include <video/mipi_display.h> |
25 | #include <video/videomode.h> | 27 | #include <video/videomode.h> |
26 | 28 | ||
29 | #include "exynos_drm_crtc.h" | ||
27 | #include "exynos_drm_drv.h" | 30 | #include "exynos_drm_drv.h" |
28 | 31 | ||
29 | /* returns true iff both arguments logically differs */ | 32 | /* returns true iff both arguments logically differs */ |
@@ -247,6 +250,7 @@ struct exynos_dsi { | |||
247 | struct clk *bus_clk; | 250 | struct clk *bus_clk; |
248 | struct regulator_bulk_data supplies[2]; | 251 | struct regulator_bulk_data supplies[2]; |
249 | int irq; | 252 | int irq; |
253 | int te_gpio; | ||
250 | 254 | ||
251 | u32 pll_clk_rate; | 255 | u32 pll_clk_rate; |
252 | u32 burst_clk_rate; | 256 | u32 burst_clk_rate; |
@@ -954,17 +958,89 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id) | |||
954 | return IRQ_HANDLED; | 958 | return IRQ_HANDLED; |
955 | } | 959 | } |
956 | 960 | ||
961 | static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id) | ||
962 | { | ||
963 | struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id; | ||
964 | struct drm_encoder *encoder = dsi->encoder; | ||
965 | |||
966 | if (dsi->state & DSIM_STATE_ENABLED) | ||
967 | exynos_drm_crtc_te_handler(encoder->crtc); | ||
968 | |||
969 | return IRQ_HANDLED; | ||
970 | } | ||
971 | |||
972 | static void exynos_dsi_enable_irq(struct exynos_dsi *dsi) | ||
973 | { | ||
974 | enable_irq(dsi->irq); | ||
975 | |||
976 | if (gpio_is_valid(dsi->te_gpio)) | ||
977 | enable_irq(gpio_to_irq(dsi->te_gpio)); | ||
978 | } | ||
979 | |||
980 | static void exynos_dsi_disable_irq(struct exynos_dsi *dsi) | ||
981 | { | ||
982 | if (gpio_is_valid(dsi->te_gpio)) | ||
983 | disable_irq(gpio_to_irq(dsi->te_gpio)); | ||
984 | |||
985 | disable_irq(dsi->irq); | ||
986 | } | ||
987 | |||
957 | static int exynos_dsi_init(struct exynos_dsi *dsi) | 988 | static int exynos_dsi_init(struct exynos_dsi *dsi) |
958 | { | 989 | { |
959 | exynos_dsi_enable_clock(dsi); | 990 | exynos_dsi_enable_clock(dsi); |
960 | exynos_dsi_reset(dsi); | 991 | exynos_dsi_reset(dsi); |
961 | enable_irq(dsi->irq); | 992 | exynos_dsi_enable_irq(dsi); |
962 | exynos_dsi_wait_for_reset(dsi); | 993 | exynos_dsi_wait_for_reset(dsi); |
963 | exynos_dsi_init_link(dsi); | 994 | exynos_dsi_init_link(dsi); |
964 | 995 | ||
965 | return 0; | 996 | return 0; |
966 | } | 997 | } |
967 | 998 | ||
999 | static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi) | ||
1000 | { | ||
1001 | int ret; | ||
1002 | |||
1003 | dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0); | ||
1004 | if (!gpio_is_valid(dsi->te_gpio)) { | ||
1005 | dev_err(dsi->dev, "no te-gpios specified\n"); | ||
1006 | ret = dsi->te_gpio; | ||
1007 | goto out; | ||
1008 | } | ||
1009 | |||
1010 | ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio"); | ||
1011 | if (ret) { | ||
1012 | dev_err(dsi->dev, "gpio request failed with %d\n", ret); | ||
1013 | goto out; | ||
1014 | } | ||
1015 | |||
1016 | /* | ||
1017 | * This TE GPIO IRQ should not be set to IRQ_NOAUTOEN, because panel | ||
1018 | * calls drm_panel_init() first then calls mipi_dsi_attach() in probe(). | ||
1019 | * It means that te_gpio is invalid when exynos_dsi_enable_irq() is | ||
1020 | * called by drm_panel_init() before panel is attached. | ||
1021 | */ | ||
1022 | ret = request_threaded_irq(gpio_to_irq(dsi->te_gpio), | ||
1023 | exynos_dsi_te_irq_handler, NULL, | ||
1024 | IRQF_TRIGGER_RISING, "TE", dsi); | ||
1025 | if (ret) { | ||
1026 | dev_err(dsi->dev, "request interrupt failed with %d\n", ret); | ||
1027 | gpio_free(dsi->te_gpio); | ||
1028 | goto out; | ||
1029 | } | ||
1030 | |||
1031 | out: | ||
1032 | return ret; | ||
1033 | } | ||
1034 | |||
1035 | static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi) | ||
1036 | { | ||
1037 | if (gpio_is_valid(dsi->te_gpio)) { | ||
1038 | free_irq(gpio_to_irq(dsi->te_gpio), dsi); | ||
1039 | gpio_free(dsi->te_gpio); | ||
1040 | dsi->te_gpio = -ENOENT; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
968 | static int exynos_dsi_host_attach(struct mipi_dsi_host *host, | 1044 | static int exynos_dsi_host_attach(struct mipi_dsi_host *host, |
969 | struct mipi_dsi_device *device) | 1045 | struct mipi_dsi_device *device) |
970 | { | 1046 | { |
@@ -978,6 +1054,19 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host, | |||
978 | if (dsi->connector.dev) | 1054 | if (dsi->connector.dev) |
979 | drm_helper_hpd_irq_event(dsi->connector.dev); | 1055 | drm_helper_hpd_irq_event(dsi->connector.dev); |
980 | 1056 | ||
1057 | /* | ||
1058 | * This is a temporary solution and should be made by more generic way. | ||
1059 | * | ||
1060 | * If attached panel device is for command mode one, dsi should register | ||
1061 | * TE interrupt handler. | ||
1062 | */ | ||
1063 | if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) { | ||
1064 | int ret = exynos_dsi_register_te_irq(dsi); | ||
1065 | |||
1066 | if (ret) | ||
1067 | return ret; | ||
1068 | } | ||
1069 | |||
981 | return 0; | 1070 | return 0; |
982 | } | 1071 | } |
983 | 1072 | ||
@@ -986,6 +1075,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host, | |||
986 | { | 1075 | { |
987 | struct exynos_dsi *dsi = host_to_dsi(host); | 1076 | struct exynos_dsi *dsi = host_to_dsi(host); |
988 | 1077 | ||
1078 | exynos_dsi_unregister_te_irq(dsi); | ||
1079 | |||
989 | dsi->panel_node = NULL; | 1080 | dsi->panel_node = NULL; |
990 | 1081 | ||
991 | if (dsi->connector.dev) | 1082 | if (dsi->connector.dev) |
@@ -1099,7 +1190,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi) | |||
1099 | 1190 | ||
1100 | exynos_dsi_disable_clock(dsi); | 1191 | exynos_dsi_disable_clock(dsi); |
1101 | 1192 | ||
1102 | disable_irq(dsi->irq); | 1193 | exynos_dsi_disable_irq(dsi); |
1103 | } | 1194 | } |
1104 | 1195 | ||
1105 | dsi->state &= ~DSIM_STATE_CMD_LPM; | 1196 | dsi->state &= ~DSIM_STATE_CMD_LPM; |
@@ -1445,6 +1536,9 @@ static int exynos_dsi_probe(struct platform_device *pdev) | |||
1445 | goto err_del_component; | 1536 | goto err_del_component; |
1446 | } | 1537 | } |
1447 | 1538 | ||
1539 | /* To be checked as invalid one */ | ||
1540 | dsi->te_gpio = -ENOENT; | ||
1541 | |||
1448 | init_completion(&dsi->completed); | 1542 | init_completion(&dsi->completed); |
1449 | spin_lock_init(&dsi->transfer_lock); | 1543 | spin_lock_init(&dsi->transfer_lock); |
1450 | INIT_LIST_HEAD(&dsi->transfer_list); | 1544 | INIT_LIST_HEAD(&dsi->transfer_list); |