static int extcon_cros_ec_detect_cable()

in extcon-usbc-cros-ec.c [247:360]


static int extcon_cros_ec_detect_cable(struct cros_ec_extcon_info *info,
				       bool force)
{
	struct device *dev = info->dev;
	int role, power_type;
	unsigned int dr = DR_NONE;
	bool pr = false;
	bool polarity = false;
	bool dp = false;
	bool mux = false;
	bool hpd = false;

	power_type = cros_ec_usb_get_power_type(info);
	if (power_type < 0) {
		dev_err(dev, "failed getting power type err = %d\n",
			power_type);
		return power_type;
	}

	role = cros_ec_usb_get_role(info, &polarity);
	if (role < 0) {
		if (role != -ENOTCONN) {
			dev_err(dev, "failed getting role err = %d\n", role);
			return role;
		}
		dev_dbg(dev, "disconnected\n");
	} else {
		int pd_mux_state;

		dr = (role & PD_CTRL_RESP_ROLE_DATA) ? DR_HOST : DR_DEVICE;
		pr = (role & PD_CTRL_RESP_ROLE_POWER);
		pd_mux_state = cros_ec_usb_get_pd_mux_state(info);
		if (pd_mux_state < 0)
			pd_mux_state = USB_PD_MUX_USB_ENABLED;

		dp = pd_mux_state & USB_PD_MUX_DP_ENABLED;
		mux = pd_mux_state & USB_PD_MUX_USB_ENABLED;
		hpd = pd_mux_state & USB_PD_MUX_HPD_IRQ;

		dev_dbg(dev,
			"connected role 0x%x pwr type %d dr %d pr %d pol %d mux %d dp %d hpd %d\n",
			role, power_type, dr, pr, polarity, mux, dp, hpd);
	}

	/*
	 * When there is no USB host (e.g. USB PD charger),
	 * we are not really a UFP for the AP.
	 */
	if (dr == DR_DEVICE &&
	    cros_ec_usb_power_type_is_wall_wart(power_type, role))
		dr = DR_NONE;

	if (force || info->dr != dr || info->pr != pr || info->dp != dp ||
	    info->mux != mux || info->power_type != power_type) {
		bool host_connected = false, device_connected = false;

		dev_dbg(dev, "Type/Role switch! type = %s role = %s\n",
			cros_ec_usb_power_type_string(power_type),
			cros_ec_usb_role_string(dr));
		info->dr = dr;
		info->pr = pr;
		info->dp = dp;
		info->mux = mux;
		info->power_type = power_type;

		if (dr == DR_DEVICE)
			device_connected = true;
		else if (dr == DR_HOST)
			host_connected = true;

		extcon_set_state(info->edev, EXTCON_USB, device_connected);
		extcon_set_state(info->edev, EXTCON_USB_HOST, host_connected);
		extcon_set_state(info->edev, EXTCON_DISP_DP, dp);
		extcon_set_property(info->edev, EXTCON_USB,
				    EXTCON_PROP_USB_VBUS,
				    (union extcon_property_value)(int)pr);
		extcon_set_property(info->edev, EXTCON_USB_HOST,
				    EXTCON_PROP_USB_VBUS,
				    (union extcon_property_value)(int)pr);
		extcon_set_property(info->edev, EXTCON_USB,
				    EXTCON_PROP_USB_TYPEC_POLARITY,
				    (union extcon_property_value)(int)polarity);
		extcon_set_property(info->edev, EXTCON_USB_HOST,
				    EXTCON_PROP_USB_TYPEC_POLARITY,
				    (union extcon_property_value)(int)polarity);
		extcon_set_property(info->edev, EXTCON_DISP_DP,
				    EXTCON_PROP_USB_TYPEC_POLARITY,
				    (union extcon_property_value)(int)polarity);
		extcon_set_property(info->edev, EXTCON_USB,
				    EXTCON_PROP_USB_SS,
				    (union extcon_property_value)(int)mux);
		extcon_set_property(info->edev, EXTCON_USB_HOST,
				    EXTCON_PROP_USB_SS,
				    (union extcon_property_value)(int)mux);
		extcon_set_property(info->edev, EXTCON_DISP_DP,
				    EXTCON_PROP_USB_SS,
				    (union extcon_property_value)(int)mux);
		extcon_set_property(info->edev, EXTCON_DISP_DP,
				    EXTCON_PROP_DISP_HPD,
				    (union extcon_property_value)(int)hpd);

		extcon_sync(info->edev, EXTCON_USB);
		extcon_sync(info->edev, EXTCON_USB_HOST);
		extcon_sync(info->edev, EXTCON_DISP_DP);

	} else if (hpd) {
		extcon_set_property(info->edev, EXTCON_DISP_DP,
				    EXTCON_PROP_DISP_HPD,
				    (union extcon_property_value)(int)hpd);
		extcon_sync(info->edev, EXTCON_DISP_DP);
	}

	return 0;
}