소스 검색

msm: camera: sensor: Handle tpg shutdown properly

CPAS stops during shutdown needs to be done only for the TPGs which has
done the cpas start. This change add the state checks while tpg reset.

CRs-Fixed: 2998830
Change-Id: I4cdd9ec74daa65999ed5094a3c4a4c165b9a1569
Signed-off-by: Tony Lijo Jose <[email protected]>
Tony Lijo Jose 4 년 전
부모
커밋
1ac3215b14

+ 40 - 17
drivers/cam_sensor_module/cam_tpg/cam_tpg_dev.c

@@ -9,6 +9,36 @@
 #include "tpg_hw/tpg_hw_v_1_0/tpg_hw_v_1_0_data.h"
 #include "tpg_hw/tpg_hw_v_1_3/tpg_hw_v_1_3_data.h"
 
+static int cam_tpg_subdev_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	struct cam_tpg_device *tpg_dev =
+		v4l2_get_subdevdata(sd);
+
+	bool crm_active = cam_req_mgr_is_open();
+
+	if (!tpg_dev) {
+		CAM_ERR(CAM_TPG, "tpg_dev ptr is NULL");
+		return -EINVAL;
+	}
+
+	if (crm_active) {
+		CAM_DBG(CAM_TPG, "CRM is ACTIVE, close should be from CRM");
+		return 0;
+	}
+
+	mutex_lock(&tpg_dev->mutex);
+	if (tpg_dev->state == CAM_TPG_STATE_INIT) {
+		CAM_DBG(CAM_TPG, "TPG node %d is succesfully closed", tpg_dev->soc_info.index);
+		mutex_unlock(&tpg_dev->mutex);
+		return 0;
+	}
+	cam_tpg_shutdown(tpg_dev);
+	mutex_unlock(&tpg_dev->mutex);
+
+	return 0;
+}
+
 static long cam_tpg_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
 {
@@ -19,6 +49,15 @@ static long cam_tpg_subdev_ioctl(struct v4l2_subdev *sd,
 	case VIDIOC_CAM_CONTROL:
 		rc = cam_tpg_core_cfg(tpg_dev, arg);
 		break;
+	case CAM_SD_SHUTDOWN:
+		if (!cam_req_mgr_is_shutdown()) {
+			CAM_ERR(CAM_CORE, "SD shouldn't come from user space");
+			return 0;
+		}
+		mutex_lock(&tpg_dev->mutex);
+		cam_tpg_shutdown(tpg_dev);
+		mutex_unlock(&tpg_dev->mutex);
+		break;
 	default:
 		CAM_ERR(CAM_TPG, "Wrong ioctl : %d", cmd);
 		rc = -ENOIOCTLCMD;
@@ -81,23 +120,6 @@ static struct v4l2_subdev_core_ops tpg_subdev_core_ops = {
 #endif
 };
 
-static int cam_tpg_subdev_close(struct v4l2_subdev *sd,
-	struct v4l2_subdev_fh *fh)
-{
-	struct cam_tpg_device *tpg_dev =
-		v4l2_get_subdevdata(sd);
-
-	if (!tpg_dev) {
-		CAM_ERR(CAM_TPG, "tpg_dev ptr is NULL");
-		return -EINVAL;
-	}
-
-	mutex_lock(&tpg_dev->mutex);
-	cam_tpg_shutdown(tpg_dev);
-	mutex_unlock(&tpg_dev->mutex);
-
-	return 0;
-}
 
 static const struct v4l2_subdev_ops tpg_subdev_ops = {
 	.core = &tpg_subdev_core_ops,
@@ -225,6 +247,7 @@ static int cam_tpg_hw_layer_init(struct cam_tpg_device *tpg_dev,
 	tpg_dev->tpg_hw.hw_info  = (struct tpg_hw_info *)match_dev->data;
 	tpg_dev->tpg_hw.soc_info = &tpg_dev->soc_info;
 	tpg_dev->tpg_hw.cpas_handle = tpg_dev->cpas_handle;
+	tpg_dev->tpg_hw.state    = TPG_HW_STATE_HW_DISABLED;
 	mutex_init(&tpg_dev->tpg_hw.mutex);
 
 	tpg_dev->tpg_hw.vc_slots = devm_kzalloc(&pdev->dev,

+ 11 - 2
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.c

@@ -240,9 +240,11 @@ static int tpg_hw_soc_disable(struct tpg_hw *hw)
 		CAM_ERR(CAM_TPG, "TPG[%d] Disable platform failed %d",
 				hw->hw_idx, rc);
 
-	if (cam_cpas_stop(hw->cpas_handle)) {
+	if ((rc = cam_cpas_stop(hw->cpas_handle))) {
 		CAM_ERR(CAM_TPG, "TPG[%d] CPAS stop failed",
 				hw->hw_idx);
+	} else {
+		hw->state = TPG_HW_STATE_HW_DISABLED;
 	}
 
 	return rc;
@@ -287,6 +289,7 @@ static int tpg_hw_soc_enable(
 				hw->hw_idx);
 		goto stop_cpas;
 	}
+	hw->state = TPG_HW_STATE_HW_ENABLED;
 
 	return rc;
 stop_cpas:
@@ -634,10 +637,16 @@ int tpg_hw_reset(struct tpg_hw *hw)
 		CAM_ERR(CAM_TPG, "TPG[%d] Unable to free up the streams", hw->hw_idx);
 
 	/* disable the hw */
-	if (cam_cpas_stop(hw->cpas_handle)) {
+	mutex_lock(&hw->mutex);
+	if ((hw->state != TPG_HW_STATE_HW_DISABLED) &&
+			cam_cpas_stop(hw->cpas_handle)) {
 		CAM_ERR(CAM_TPG, "TPG[%d] CPAS stop failed",
 				hw->hw_idx);
+		rc = -EINVAL;
+	} else {
+		hw->state = TPG_HW_STATE_HW_DISABLED;
 	}
+	mutex_unlock(&hw->mutex);
 
 	return rc;
 }

+ 11 - 0
drivers/cam_sensor_module/cam_tpg/tpg_hw/tpg_hw.h

@@ -42,6 +42,17 @@ struct tpg_hw_ops {
 	int (*dump_status)(struct tpg_hw *hw, void *data);
 };
 
+/**
+ * tpg_hw_state : tpg hw states
+ *
+ * TPG_HW_STATE_HW_DISABLED: tpg hw is not enabled yet
+ * TPG_HW_STATE_HW_ENABLED : tpg hw is enabled
+ */
+enum tpg_hw_state {
+	TPG_HW_STATE_HW_DISABLED,
+	TPG_HW_STATE_HW_ENABLED,
+};
+
 /**
  * @brief tpg_vc_slot_info
  * @slot_id      : slot id of this vc slot