Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ee6a6aa authored by YUE CHEN's avatar YUE CHEN Committed by Gerrit - the friendly Code Review server
Browse files

msm: ais: implement bridge error report



Configure the gpios as irq mode, send the event
to ais when error detected.

Change-Id: I6aaa6e002fbcea4013e2e80c34052f62ad8b604e
Signed-off-by: default avatarYUE CHEN <yueche@codeaurora.org>
parent 2ba5ea33
Loading
Loading
Loading
Loading
+154 −2
Original line number Diff line number Diff line
@@ -456,6 +456,91 @@ int32_t cam_sensor_update_slave_info(struct cam_cmd_probe *probe_info,
	return rc;
}


static void bridge_irq_work(struct work_struct *work)
{
	struct cam_sensor_ctrl_t *s_ctrl;
	struct cam_sensor_intr_t *s_intr;
	struct v4l2_event event;

	s_intr = container_of(work, struct cam_sensor_intr_t,
					irq_work);
	s_ctrl = s_intr->sctrl;

	mutex_lock(&s_ctrl->cam_sensor_mutex);

	/* Queue the event */
	memset(&event, 0, sizeof(struct v4l2_event));
	event.id = s_intr->gpio_array[0].gpio;
	event.type = AIS_SENSOR_EVENT_TYPE;
	v4l2_event_queue(s_ctrl->v4l2_dev_str.sd.devnode, &event);

	mutex_unlock(&s_ctrl->cam_sensor_mutex);
}


static irqreturn_t bridge_irq(int irq_num, void *dev)
{
	struct cam_sensor_intr_t *s_intr = dev;

	schedule_work(&s_intr->irq_work);

	return IRQ_HANDLED;
}

static int32_t cam_sensor_init_gpio_intr(
	struct ais_sensor_gpio_intr_config *gpio_intr_info,
	struct cam_sensor_ctrl_t *s_ctrl)
{
	int32_t rc = -1;
	int32_t gpio_num = 0;
	int32_t gpio_cfg0 = 0;
	int32_t idx = 0;

	for (idx = 0; idx < AIS_MAX_INTR_GPIO; idx++) {
		if (!s_ctrl->s_intr[idx].work_inited &&
			gpio_intr_info->gpio_num != -1) {
			gpio_num = gpio_intr_info->gpio_num;

			gpio_cfg0 = gpio_intr_info->gpio_cfg0;

			s_ctrl->s_intr[idx].sctrl = s_ctrl;

			s_ctrl->s_intr[idx].gpio_array[0].gpio = gpio_num;

			INIT_WORK(&s_ctrl->s_intr[idx].irq_work,
				bridge_irq_work);

			rc = gpio_request_one(gpio_num,
						GPIOF_DIR_IN, "camera_intr");

			if (!rc) {
				rc = request_irq(gpio_to_irq(gpio_num),
					bridge_irq,
					IRQF_ONESHOT | gpio_cfg0,
					"qcom,ais",
					&s_ctrl->s_intr[idx]);

				if (rc < 0)
					CAM_ERR(CAM_SENSOR,
					"gpio %d request irq failed", gpio_num);
			} else {
				gpio_free(gpio_num);
				CAM_ERR(CAM_SENSOR,
				"gpio %d request failed", gpio_num);
			}

			if (!rc)
				s_ctrl->s_intr[idx].work_inited = 1;

			break;
		}
	}

	return rc;
}


int32_t cam_handle_cmd_buffers_for_probe(void *cmd_buf,
	struct cam_sensor_ctrl_t *s_ctrl,
	int32_t cmd_buf_num, uint32_t cmd_buf_length, size_t remain_len)
@@ -841,14 +926,13 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
		probe_cmd = kzalloc(sizeof(*probe_cmd), GFP_KERNEL);
		if (!probe_cmd) {
			rc = -ENOMEM;
			goto free_probe_cmd;
			goto release_mutex;
		}

		rc = copy_from_user(probe_cmd,
			(void __user *) cmd->handle, sizeof(*probe_cmd));
		if (rc < 0) {
			CAM_ERR(CAM_SENSOR, "Failed Copying from user");
			kfree(probe_cmd);
			goto free_probe_cmd;
		}

@@ -1184,6 +1268,74 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
		kfree(reg_setting);
	}
		break;
	case AIS_SENSOR_INTR_INIT: {
		struct ais_sensor_gpio_intr_config
			*gpio_intr_cfg;

		gpio_intr_cfg =
			kzalloc(sizeof(struct ais_sensor_gpio_intr_config),
			GFP_KERNEL);

		if (!gpio_intr_cfg) {
			rc = -ENOMEM;
			goto release_mutex;
		}

		rc = copy_from_user(gpio_intr_cfg,
			(void __user *) cmd->handle,
			sizeof(struct ais_sensor_gpio_intr_config));

		if (rc < 0) {
			CAM_ERR(CAM_SENSOR, "Failed Copying from user");
			goto free_gpio_intr_init_config;
		}

		rc = cam_sensor_init_gpio_intr(
				gpio_intr_cfg,
				s_ctrl);

		if (rc < 0)
			CAM_ERR(CAM_SENSOR, "Failed in Updating intr Info");

free_gpio_intr_init_config:
		kfree(gpio_intr_cfg);

	}
		break;
	case AIS_SENSOR_INTR_DEINIT: {
		int idx = 0;
		int rc = 0;
		struct ais_sensor_gpio_intr_config
			*gpio_intr_cfg;

		gpio_intr_cfg =
			kzalloc(sizeof(struct ais_sensor_gpio_intr_config),
			GFP_KERNEL);

		if (!gpio_intr_cfg) {
			rc = -ENOMEM;
			goto release_mutex;
		}

		rc = copy_from_user(gpio_intr_cfg,
			(void __user *) cmd->handle,
			sizeof(struct ais_sensor_gpio_intr_config));

		if (rc < 0) {
			CAM_ERR(CAM_SENSOR, "Failed Copying from user");
			goto free_gpio_intr_deinit_config;
		}

		for (idx = 0; idx < AIS_MAX_INTR_GPIO; idx++) {
			if (s_ctrl->s_intr[idx].work_inited == 1)
				cancel_work_sync(
				&s_ctrl->s_intr[idx].irq_work);
		}

free_gpio_intr_deinit_config:
		kfree(gpio_intr_cfg);
	}
		break;
	case CAM_ACQUIRE_DEV: {
		struct cam_sensor_acquire_dev sensor_acq_dev;
		struct cam_create_dev_hdl bridge_params;
+17 −0
Original line number Diff line number Diff line
@@ -15,6 +15,21 @@
#include "cam_sensor_soc.h"
#include "cam_sensor_core.h"


static int cam_sensor_subdev_subscribe_event(struct v4l2_subdev *sd,
	struct v4l2_fh *fh,
	struct v4l2_event_subscription *sub)
{
	return v4l2_event_subscribe(fh, sub, CAM_SUBDEVICE_EVENT_MAX, NULL);
}

static int cam_sensor_subdev_unsubscribe_event(struct v4l2_subdev *sd,
	struct v4l2_fh *fh,
	struct v4l2_event_subscription *sub)
{
	return v4l2_event_unsubscribe(fh, sub);
}

static long cam_sensor_subdev_ioctl(struct v4l2_subdev *sd,
	unsigned int cmd, void *arg)
{
@@ -97,6 +112,8 @@ static struct v4l2_subdev_core_ops cam_sensor_subdev_core_ops = {
	.compat_ioctl32 = cam_sensor_init_subdev_do_ioctl,
#endif
	.s_power = cam_sensor_power,
	.subscribe_event = cam_sensor_subdev_subscribe_event,
	.unsubscribe_event = cam_sensor_subdev_unsubscribe_event,
};

static struct v4l2_subdev_ops cam_sensor_subdev_ops = {
+8 −0
Original line number Diff line number Diff line
@@ -73,6 +73,13 @@ struct intf_params {
	struct cam_req_mgr_crm_cb *crm_cb;
};

struct cam_sensor_intr_t {
	struct cam_sensor_ctrl_t *sctrl;
	struct gpio gpio_array[1];
	int work_inited;
	struct work_struct irq_work;
};

/**
 * struct cam_sensor_ctrl_t: Camera control structure
 * @device_name: Sensor device name
@@ -123,6 +130,7 @@ struct cam_sensor_ctrl_t {
	bool bob_pwm_switch;
	uint32_t last_flush_req;
	uint16_t pipeline_delay;
	struct cam_sensor_intr_t s_intr[AIS_MAX_INTR_GPIO];
};

#endif /* _CAM_SENSOR_DEV_H_ */
+2 −2
Original line number Diff line number Diff line
@@ -15,8 +15,8 @@
#include "cam_mem_mgr.h"
#include "cam_res_mgr_api.h"

#define CAM_SENSOR_PINCTRL_STATE_SLEEP "cam_suspend"
#define CAM_SENSOR_PINCTRL_STATE_DEFAULT "cam_default"
#define CAM_SENSOR_PINCTRL_STATE_SLEEP "sensor_suspend"
#define CAM_SENSOR_PINCTRL_STATE_DEFAULT "sensor_default"

#define VALIDATE_VOLTAGE(min, max, config_val) ((config_val) && \
	(config_val >= min) && (config_val <= max))
+7 −6
Original line number Diff line number Diff line
@@ -12,13 +12,14 @@
#define AIS_SENSOR_I2C_WRITE_ARRAY (AIS_SENSOR_OPCODE_START + 6)
#define AIS_SENSOR_I2C_POWER_UP    (AIS_SENSOR_OPCODE_START + 7)
#define AIS_SENSOR_I2C_POWER_DOWN  (AIS_SENSOR_OPCODE_START + 8)

#define AIS_SENSOR_INTR_INIT      (AIS_SENSOR_OPCODE_START + 9)
#define AIS_SENSOR_INTR_DEINIT    (AIS_SENSOR_OPCODE_START + 10)
#define AIS_SENSOR_EVENT_BASE      (V4L2_EVENT_PRIVATE_START)
#define AIS_SENSOR_EVENT_TYPE      (AIS_SENSOR_EVENT_BASE + 1)


#define AIS_MAX_POWER_SEQ 12

#define AIS_MAX_INTR_GPIO 3

struct ais_sensor_event_data {
	uint32_t data[16];
@@ -79,7 +80,7 @@ struct ais_sensor_gpio_intr_config {
struct ais_sensor_probe_cmd {
	struct cam_cmd_i2c_info i2c_config;
	struct ais_sensor_power_config power_config;
	struct ais_sensor_gpio_intr_config gpio_intr_config[3];
	struct ais_sensor_gpio_intr_config gpio_intr_config[AIS_MAX_INTR_GPIO];
};

/**