Переглянути джерело

disp: msm: dp: Add abstract and wcd939x aux switch support

Add functionality to change which aux switch is used
at compile time for different targets. Add wcd939x
switch support.

Change-Id: Iced3b11733009680063790dfa8f180b19002f963
Signed-off-by: Nisarg Bhavsar <[email protected]>
Nisarg Bhavsar 2 роки тому
батько
коміт
4a2e5b3fe1
5 змінених файлів з 92 додано та 17 видалено
  1. 1 0
      config/gki_kalamadisp.conf
  2. 1 0
      config/gki_kalamadispconf.h
  3. 72 3
      msm/dp/dp_aux.c
  4. 4 3
      msm/dp/dp_aux.h
  5. 14 11
      msm/dp/dp_display.c

+ 1 - 0
config/gki_kalamadisp.conf

@@ -15,3 +15,4 @@ export CONFIG_HDCP_QSEECOM=y
 export CONFIG_DRM_SDE_VM=y
 export CONFIG_QTI_HW_FENCE=y
 export CONFIG_QCOM_SPEC_SYNC=y
+export CONFIG_QCOM_FSA4480_I2C=y

+ 1 - 0
config/gki_kalamadispconf.h

@@ -23,3 +23,4 @@
 #define CONFIG_DRM_SDE_VM 1
 #define CONFIG_QTI_HW_FENCE 1
 #define CONFIG_QCOM_SPEC_SYNC 1
+#define CONFIG_QCOM_FSA4480_I2C 1

+ 72 - 3
msm/dp/dp_aux.c

@@ -4,9 +4,14 @@
  * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
  */
 
-#include <linux/soc/qcom/fsa4480-i2c.h>
 #include <linux/delay.h>
 
+#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
+#include <linux/soc/qcom/fsa4480-i2c.h>
+#elif IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
+#include <linux/soc/qcom/wcd939x-i2c.h>
+#endif
+
 #include "dp_aux.h"
 #include "dp_hpd.h"
 #include "dp_debug.h"
@@ -755,7 +760,8 @@ static void dp_aux_set_sim_mode(struct dp_aux *dp_aux,
 	mutex_unlock(&aux->mutex);
 }
 
-static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux,
+#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
+static int dp_aux_configure_fsa_switch(struct dp_aux *dp_aux,
 		bool enable, int orientation)
 {
 	struct dp_aux_private *aux;
@@ -795,11 +801,65 @@ static int dp_aux_configure_aux_switch(struct dp_aux *dp_aux,
 			enable, orientation, event);
 
 	rc = fsa4480_switch_event(aux->aux_switch_node, event);
+
 	if (rc)
 		DP_AUX_ERR(dp_aux, "failed to configure fsa4480 i2c device (%d)\n", rc);
 end:
 	return rc;
 }
+#endif
+
+#if IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
+static int dp_aux_configure_wcd_switch(struct dp_aux *dp_aux,
+		bool enable, int orientation)
+{
+	struct dp_aux_private *aux;
+	int rc = 0;
+	enum wcd_usbss_cable_status status = WCD_USBSS_CABLE_DISCONNECT;
+	enum wcd_usbss_cable_types event = WCD_USBSS_DP_AUX_CC1;
+
+	if (!dp_aux) {
+		DP_AUX_ERR(dp_aux, "invalid input\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	if (!aux->aux_switch_node) {
+		DP_AUX_DEBUG(dp_aux, "undefined wcd939x switch handle\n");
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (enable) {
+		status = WCD_USBSS_CABLE_CONNECT;
+
+		switch (orientation) {
+		case ORIENTATION_CC1:
+			event = WCD_USBSS_DP_AUX_CC1;
+			break;
+		case ORIENTATION_CC2:
+			event = WCD_USBSS_DP_AUX_CC2;
+			break;
+		default:
+			DP_AUX_ERR(dp_aux, "invalid orientation\n");
+			rc = -EINVAL;
+			goto end;
+		}
+	}
+
+	DP_AUX_DEBUG(dp_aux, "enable=%d, orientation=%d, event=%d\n",
+			enable, orientation, event);
+
+	rc = wcd_usbss_switch_update(event, status);
+
+	if (rc)
+		DP_AUX_ERR(dp_aux, "failed to configure wcd939x i2c device (%d)\n", rc);
+end:
+	return rc;
+}
+#endif
 
 struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
 		struct dp_parser *parser, struct device_node *aux_switch,
@@ -841,7 +901,16 @@ struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
 	dp_aux->reconfig = dp_aux_reconfig;
 	dp_aux->abort = dp_aux_abort_transaction;
 	dp_aux->set_sim_mode = dp_aux_set_sim_mode;
-	dp_aux->aux_switch = dp_aux_configure_aux_switch;
+
+#if IS_ENABLED(CONFIG_QCOM_FSA4480_I2C)
+	dp_aux->switch_configure = dp_aux_configure_fsa_switch;
+	dp_aux->switch_register_notifier = fsa4480_reg_notifier;
+	dp_aux->switch_unregister_notifier = fsa4480_unreg_notifier;
+#elif IS_ENABLED(CONFIG_QCOM_WCD939X_I2C)
+	dp_aux->switch_configure = dp_aux_configure_wcd_switch;
+	dp_aux->switch_register_notifier = wcd_usbss_reg_notifier;
+	dp_aux->switch_unregister_notifier = wcd_usbss_unreg_notifier;
+#endif
 
 	return dp_aux;
 error:

+ 4 - 3
msm/dp/dp_aux.h

@@ -56,9 +56,10 @@ struct dp_aux {
 	void (*deinit)(struct dp_aux *aux);
 	void (*reconfig)(struct dp_aux *aux);
 	void (*abort)(struct dp_aux *aux, bool abort);
-	void (*set_sim_mode)(struct dp_aux *aux,
-		struct dp_aux_bridge *sim_bridge);
-	int (*aux_switch)(struct dp_aux *aux, bool enable, int orientation);
+	void (*set_sim_mode)(struct dp_aux *aux, struct dp_aux_bridge *sim_bridge);
+	int (*switch_configure)(struct dp_aux *aux, bool enable, int orientation);
+	int (*switch_register_notifier)(struct notifier_block *nb, struct device_node *node);
+	int (*switch_unregister_notifier)(struct notifier_block *nb, struct device_node *node);
 };
 
 struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,

+ 14 - 11
msm/dp/dp_display.c

@@ -11,7 +11,6 @@
 #include <linux/component.h>
 #include <linux/of_irq.h>
 #include <linux/delay.h>
-#include <linux/soc/qcom/fsa4480-i2c.h>
 #include <linux/usb/phy.h>
 #include <linux/jiffies.h>
 #include <linux/pm_qos.h>
@@ -1221,8 +1220,8 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
 					dp->debug->max_pclk_khz);
 
 	if (!dp->debug->sim_mode && !dp->no_aux_switch && !dp->parser->gpio_aux_switch
-			&& dp->aux_switch_node) {
-		rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation);
+			&& dp->aux_switch_node && dp->aux->switch_configure) {
+		rc = dp->aux->switch_configure(dp->aux, true, dp->hpd->orientation);
 		if (rc) {
 			mutex_unlock(&dp->session_lock);
 			return rc;
@@ -1400,7 +1399,7 @@ static int dp_display_process_hpd_low(struct dp_display_private *dp, bool skip_w
 	return rc;
 }
 
-static int dp_display_fsa4480_callback(struct notifier_block *self,
+static int dp_display_aux_switch_callback(struct notifier_block *self,
 		unsigned long event, void *data)
 {
 	return 0;
@@ -1416,9 +1415,12 @@ static int dp_display_init_aux_switch(struct dp_display_private *dp)
 	if (dp->aux_switch_ready)
 	       return rc;
 
+	if (!dp->aux->switch_register_notifier)
+		return rc;
+
 	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_ENTRY);
 
-	nb.notifier_call = dp_display_fsa4480_callback;
+	nb.notifier_call = dp_display_aux_switch_callback;
 	nb.priority = 0;
 
 	/*
@@ -1426,7 +1428,7 @@ static int dp_display_init_aux_switch(struct dp_display_private *dp)
 	 * Bootup DP with cable connected usecase can hit this scenario.
 	 */
 	for (retry = 0; retry < max_retries; retry++) {
-		rc = fsa4480_reg_notifier(&nb, dp->aux_switch_node);
+		rc = dp->aux->switch_register_notifier(&nb, dp->aux_switch_node);
 		if (rc == 0) {
 			DP_DEBUG("registered notifier successfully\n");
 			dp->aux_switch_ready = true;
@@ -1443,7 +1445,8 @@ static int dp_display_init_aux_switch(struct dp_display_private *dp)
 		return rc;
 	}
 
-	fsa4480_unreg_notifier(&nb, dp->aux_switch_node);
+	if (dp->aux->switch_unregister_notifier)
+		dp->aux->switch_unregister_notifier(&nb, dp->aux_switch_node);
 
 	SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, rc);
 	return rc;
@@ -1466,12 +1469,12 @@ static int dp_display_usbpd_configure_cb(struct device *dev)
 	}
 
 	if (!dp->debug->sim_mode && !dp->no_aux_switch
-	    && !dp->parser->gpio_aux_switch && dp->aux_switch_node) {
+	    && !dp->parser->gpio_aux_switch && dp->aux_switch_node && dp->aux->switch_configure) {
 		rc = dp_display_init_aux_switch(dp);
 		if (rc)
 			return rc;
 
-		rc = dp->aux->aux_switch(dp->aux, true, dp->hpd->orientation);
+		rc = dp->aux->switch_configure(dp->aux, true, dp->hpd->orientation);
 		if (rc)
 			return rc;
 	}
@@ -1656,8 +1659,8 @@ static void dp_display_disconnect_sync(struct dp_display_private *dp)
 	flush_workqueue(dp->wq);
 
 	if (!dp->debug->sim_mode && !dp->no_aux_switch
-	    && !dp->parser->gpio_aux_switch)
-		dp->aux->aux_switch(dp->aux, false, ORIENTATION_NONE);
+	    && !dp->parser->gpio_aux_switch && dp->aux->switch_configure)
+		dp->aux->switch_configure(dp->aux, false, ORIENTATION_NONE);
 
 	/*
 	 * Delay the teardown of the mainlink for better interop experience.