summaryrefslogtreecommitdiff
path: root/syna_tcm2.c
diff options
context:
space:
mode:
authordavidycchen <davidycchen@google.com>2021-09-22 15:54:21 +0800
committerdavidycchen <davidycchen@google.com>2021-09-30 14:26:24 +0800
commit8dbeaa2288f4b3dcf8ed4a28a56eab5aed82dfa6 (patch)
treed00360c78e4f8baf7c2bd426e3c2e173796ef861 /syna_tcm2.c
parentb1dd3f807cf4d1fe152ee09cca0f08b910c65248 (diff)
downloadsynaptics_touch-8dbeaa2288f4b3dcf8ed4a28a56eab5aed82dfa6.tar.gz
synaptics: use drm_bridge for touch power sequence
Listen to display states by drm_bridge for touch suspend/resume. Bug: 199104450 Bug: 201375583 Signed-off-by: davidycchen <davidycchen@google.com> Change-Id: Ie88153c7b53971bb2441b6c01cca17ea9bb12dc0
Diffstat (limited to 'syna_tcm2.c')
-rw-r--r--syna_tcm2.c125
1 files changed, 122 insertions, 3 deletions
diff --git a/syna_tcm2.c b/syna_tcm2.c
index f1bac86..6f921fb 100644
--- a/syna_tcm2.c
+++ b/syna_tcm2.c
@@ -48,6 +48,10 @@
#ifdef MULTICHIP_DUT_REFLASH
#include "synaptics_touchcom_func_romboot.h"
#endif
+#if defined(USE_DRM_BRIDGE)
+#include <samsung/exynos_drm_connector.h>
+#include <samsung/panel/panel-samsung-drv.h>
+#endif
/**
* @section: USE_CUSTOM_TOUCH_REPORT_CONFIG
@@ -1258,6 +1262,117 @@ static int syna_dev_fb_notifier_cb(struct notifier_block *nb,
}
#endif
+#if defined(USE_DRM_BRIDGE)
+struct drm_connector *syna_get_bridge_connector(struct drm_bridge *bridge)
+{
+ struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
+
+ drm_connector_list_iter_begin(bridge->dev, &conn_iter);
+ drm_for_each_connector_iter(connector, &conn_iter) {
+ if (connector->encoder == bridge->encoder)
+ break;
+ }
+ drm_connector_list_iter_end(&conn_iter);
+ return connector;
+}
+
+static bool syna_bridge_is_lp_mode(struct drm_connector *connector)
+{
+ if (connector && connector->state) {
+ struct exynos_drm_connector_state *s =
+ to_exynos_connector_state(connector->state);
+ return s->exynos_mode.is_lp_mode;
+ }
+ return false;
+}
+
+static void syna_panel_bridge_enable(struct drm_bridge *bridge)
+{
+ struct syna_tcm *tcm =
+ container_of(bridge, struct syna_tcm, panel_bridge);
+
+ pr_debug("%s\n", __func__);
+ if (!tcm ->is_panel_lp_mode)
+ syna_dev_resume(&tcm->pdev->dev);
+}
+
+static void syna_panel_bridge_disable(struct drm_bridge *bridge)
+{
+ struct syna_tcm *tcm =
+ container_of(bridge, struct syna_tcm, panel_bridge);
+
+ if (bridge->encoder && bridge->encoder->crtc) {
+ const struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
+
+ if (drm_atomic_crtc_effectively_active(crtc_state))
+ return;
+ }
+
+ pr_debug("%s\n", __func__);
+ syna_dev_suspend(&tcm->pdev->dev);
+}
+
+static void syna_panel_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adjusted_mode)
+{
+ struct syna_tcm *tcm =
+ container_of(bridge, struct syna_tcm, panel_bridge);
+
+ pr_debug("%s\n", __func__);
+
+ if (!tcm->connector || !tcm->connector->state) {
+ pr_info("%s: Get bridge connector.\n", __func__);
+ tcm->connector = syna_get_bridge_connector(bridge);
+ }
+
+ tcm->is_panel_lp_mode = syna_bridge_is_lp_mode(tcm->connector);
+ if (tcm->is_panel_lp_mode)
+ syna_dev_suspend(&tcm->pdev->dev);
+ else
+ syna_dev_resume(&tcm->pdev->dev);
+}
+
+static const struct drm_bridge_funcs panel_bridge_funcs = {
+ .enable = syna_panel_bridge_enable,
+ .disable = syna_panel_bridge_disable,
+ .mode_set = syna_panel_bridge_mode_set,
+};
+
+static int syna_register_panel_bridge(struct syna_tcm *tcm)
+{
+#ifdef CONFIG_OF
+ tcm->panel_bridge.of_node = tcm->pdev->dev.parent->of_node;
+#endif
+ tcm->panel_bridge.funcs = &panel_bridge_funcs;
+ drm_bridge_add(&tcm->panel_bridge);
+
+ return 0;
+}
+
+static void syna_unregister_panel_bridge(struct drm_bridge *bridge)
+{
+ struct drm_bridge *node;
+
+ drm_bridge_remove(bridge);
+
+ if (!bridge->dev) /* not attached */
+ return;
+
+ drm_modeset_lock(&bridge->dev->mode_config.connection_mutex, NULL);
+ list_for_each_entry(node, &bridge->encoder->bridge_chain, chain_node)
+ if (node == bridge) {
+ if (bridge->funcs->detach)
+ bridge->funcs->detach(bridge);
+ list_del(&bridge->chain_node);
+ break;
+ }
+ drm_modeset_unlock(&bridge->dev->mode_config.connection_mutex);
+ bridge->dev = NULL;
+}
+#endif
+
/**
* syna_dev_disconnect()
*
@@ -1550,7 +1665,9 @@ static int syna_dev_probe(struct platform_device *pdev)
}
#endif
-#if defined(ENABLE_DISP_NOTIFIER)
+#if defined(USE_DRM_BRIDGE)
+ retval = syna_register_panel_bridge(tcm);
+#elif defined(ENABLE_DISP_NOTIFIER)
#if defined(USE_DRM_PANEL_NOTIFIER)
dev = syna_request_managed_device();
active_panel = syna_dev_get_panel(dev->of_node);
@@ -1618,7 +1735,9 @@ static int syna_dev_remove(struct platform_device *pdev)
return 0;
}
-#if defined(ENABLE_DISP_NOTIFIER)
+#if defined(USE_DRM_BRIDGE)
+ syna_unregister_panel_bridge(&tcm->panel_bridge);
+#elif defined(ENABLE_DISP_NOTIFIER)
#if defined(USE_DRM_PANEL_NOTIFIER)
if (active_panel)
drm_panel_notifier_unregister(active_panel,
@@ -1672,7 +1791,7 @@ static void syna_dev_shutdown(struct platform_device *pdev)
*/
#ifdef CONFIG_PM
static const struct dev_pm_ops syna_dev_pm_ops = {
-#if !defined(ENABLE_DISP_NOTIFIER)
+#if !defined(ENABLE_DISP_NOTIFIER) && !defined(USE_DRM_BRIDGE)
.suspend = syna_dev_suspend,
.resume = syna_dev_resume,
#endif