diff options
author | davidycchen <davidycchen@google.com> | 2021-09-22 15:54:21 +0800 |
---|---|---|
committer | davidycchen <davidycchen@google.com> | 2021-09-30 14:26:24 +0800 |
commit | 8dbeaa2288f4b3dcf8ed4a28a56eab5aed82dfa6 (patch) | |
tree | d00360c78e4f8baf7c2bd426e3c2e173796ef861 /syna_tcm2.c | |
parent | b1dd3f807cf4d1fe152ee09cca0f08b910c65248 (diff) | |
download | synaptics_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.c | 125 |
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 |