Commit 401e0e41 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

media: atomisp: Drop support for streaming from 2 sensors at once

With support for depth mode gone there really is no need to support
streaming from 2 sensors at once. As discussed and acked on the list
(see Link tag) it is desirable to drop support for this since it
involves quite a lot of special handling / hacks in the code.

This initial commit limits itself to a minimum set of changes to switch
to 1 struct atomisp_sub_device / 1 stream. Further commits will actually
remove / cleanup much of the special handling.

Likewise this initial commit also deliberately skips the opportunity to
turn some multi-line statements into single-line statements, so as to
keep the diff small / easier to review.

Link: https://lore.kernel.org/linux-media/5309d845-063b-6dd9-529d-0f82654290f2@redhat.com/



Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent df1697fa
Loading
Loading
Loading
Loading
+46 −116
Original line number Diff line number Diff line
@@ -196,8 +196,6 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
			 enum atomisp_dfs_mode mode,
			 bool force)
{
	/* FIXME! Only use subdev[0] status yet */
	struct atomisp_sub_device *asd = &isp->asd[0];
	const struct atomisp_dfs_config *dfs;
	unsigned int new_freq;
	struct atomisp_freq_scaling_rule curr_rules;
@@ -223,7 +221,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
		goto done;
	}

	fps = atomisp_get_sensor_fps(asd);
	fps = atomisp_get_sensor_fps(&isp->asd);
	if (fps == 0) {
		dev_info(isp->dev,
			 "Sensor didn't report FPS. Using DFS max mode.\n");
@@ -231,10 +229,10 @@ int atomisp_freq_scaling(struct atomisp_device *isp,
		goto done;
	}

	curr_rules.width = asd->fmt[asd->capture_pad].fmt.width;
	curr_rules.height = asd->fmt[asd->capture_pad].fmt.height;
	curr_rules.width = isp->asd.fmt[isp->asd.capture_pad].fmt.width;
	curr_rules.height = isp->asd.fmt[isp->asd.capture_pad].fmt.height;
	curr_rules.fps = fps;
	curr_rules.run_mode = asd->run_mode->val;
	curr_rules.run_mode = isp->asd.run_mode->val;

	/* search for the target frequency by looping freq rules*/
	for (i = 0; i < dfs->dfs_table_size; i++) {
@@ -451,37 +449,13 @@ static void clear_irq_reg(struct atomisp_device *isp)
	pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg_ret);
}

static struct atomisp_sub_device *
__get_asd_from_port(struct atomisp_device *isp, enum mipi_port_id port)
{
	int i;

	/* Check which isp subdev to send eof */
	for (i = 0; i < isp->num_of_streams; i++) {
		struct atomisp_sub_device *asd = &isp->asd[i];
		struct camera_mipi_info *mipi_info;

		mipi_info = atomisp_to_sensor_mipi_info(
				isp->inputs[asd->input_curr].camera);

		if (asd->streaming == ATOMISP_DEVICE_STREAMING_ENABLED &&
		    __get_mipi_port(isp, mipi_info->port) == port) {
			return asd;
		}
	}

	return NULL;
}

/* interrupt handling function*/
irqreturn_t atomisp_isr(int irq, void *dev)
{
	struct atomisp_device *isp = (struct atomisp_device *)dev;
	struct atomisp_sub_device *asd;
	struct atomisp_css_event eof_event;
	unsigned int irq_infos = 0;
	unsigned long flags;
	unsigned int i;
	int err;

	spin_lock_irqsave(&isp->lock, flags);
@@ -501,18 +475,10 @@ irqreturn_t atomisp_isr(int irq, void *dev)
	if (!atomisp_streaming_count(isp))
		goto out_nowake;

	for (i = 0; i < isp->num_of_streams; i++) {
		asd = &isp->asd[i];

		if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
			continue;
		/*
		 * Current SOF only support one stream, so the SOF only valid
		 * either solely one stream is running
		 */
	if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED) {
		if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
			atomic_inc(&asd->sof_count);
			atomisp_sof_event(asd);
			atomic_inc(&isp->asd.sof_count);
			atomisp_sof_event(&isp->asd);

			/* If sequence_temp and sequence are the same
			 * there where no frames lost so we can increase
@@ -522,14 +488,14 @@ irqreturn_t atomisp_isr(int irq, void *dev)
			 * NOTE: There is assumption here that ISP will not
			 * start processing next frame from sensor before old
			 * one is completely done. */
			if (atomic_read(&asd->sequence) == atomic_read(
				&asd->sequence_temp))
				atomic_set(&asd->sequence_temp,
					   atomic_read(&asd->sof_count));
			if (atomic_read(&isp->asd.sequence) ==
			    atomic_read(&isp->asd.sequence_temp))
				atomic_set(&isp->asd.sequence_temp,
					   atomic_read(&isp->asd.sof_count));
		}
		if (irq_infos & IA_CSS_IRQ_INFO_EVENTS_READY)
			atomic_set(&asd->sequence,
				   atomic_read(&asd->sequence_temp));
			atomic_set(&isp->asd.sequence,
				   atomic_read(&isp->asd.sequence_temp));
	}

	if (irq_infos & IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF) {
@@ -554,21 +520,12 @@ irqreturn_t atomisp_isr(int irq, void *dev)
	}

	if (irq_infos & IA_CSS_IRQ_INFO_ISYS_EVENTS_READY) {
		while (ia_css_dequeue_isys_event(&eof_event.event) ==
		       0) {
			/* EOF Event does not have the css_pipe returned */
			asd = __get_asd_from_port(isp, eof_event.event.port);
			if (!asd) {
				dev_err(isp->dev, "%s: ISYS event, but no subdev.event:%d",
					__func__, eof_event.event.type);
				continue;
			}

			atomisp_eof_event(asd, eof_event.event.exp_id);
		while (ia_css_dequeue_isys_event(&eof_event.event) == 0) {
			atomisp_eof_event(&isp->asd, eof_event.event.exp_id);
			dev_dbg_ratelimited(isp->dev,
					    "%s ISYS event: EOF exp_id %d, asd %d\n",
					    __func__, eof_event.event.exp_id,
					    asd->index);
					    isp->asd.index);
		}

		irq_infos &= ~IA_CSS_IRQ_INFO_ISYS_EVENTS_READY;
@@ -993,9 +950,9 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
{
	struct pci_dev *pdev = to_pci_dev(isp->dev);
	enum ia_css_pipe_id css_pipe_id;
	bool stream_restart[MAX_STREAM_NUM] = {0};
	bool stream_restart = false;
	unsigned long flags;
	int i, ret;
	int ret;

	lockdep_assert_held(&isp->mutex);

@@ -1004,44 +961,37 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)

	atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF, false);

	BUG_ON(isp->num_of_streams > MAX_STREAM_NUM);

	for (i = 0; i < isp->num_of_streams; i++) {
		struct atomisp_sub_device *asd = &isp->asd[i];

		if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED &&
		    !asd->stream_prepared)
			continue;

		stream_restart[asd->index] = true;
	if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED ||
	    isp->asd.stream_prepared) {
		stream_restart = true;

		spin_lock_irqsave(&isp->lock, flags);
		asd->streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
		isp->asd.streaming = ATOMISP_DEVICE_STREAMING_STOPPING;
		spin_unlock_irqrestore(&isp->lock, flags);

		/* stream off sensor */
		ret = v4l2_subdev_call(
			  isp->inputs[asd->input_curr].
			  isp->inputs[isp->asd.input_curr].
			  camera, video, s_stream, 0);
		if (ret)
			dev_warn(isp->dev,
				 "can't stop streaming on sensor!\n");

		atomisp_clear_css_buffer_counters(asd);
		atomisp_clear_css_buffer_counters(&isp->asd);

		css_pipe_id = atomisp_get_css_pipe_id(asd);
		atomisp_css_stop(asd, css_pipe_id, true);
		css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
		atomisp_css_stop(&isp->asd, css_pipe_id, true);

		spin_lock_irqsave(&isp->lock, flags);
		asd->streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
		isp->asd.streaming = ATOMISP_DEVICE_STREAMING_DISABLED;
		spin_unlock_irqrestore(&isp->lock, flags);

		asd->preview_exp_id = 1;
		asd->postview_exp_id = 1;
		isp->asd.preview_exp_id = 1;
		isp->asd.postview_exp_id = 1;
		/* notify HAL the CSS reset */
		dev_dbg(isp->dev,
			"send reset event to %s\n", asd->subdev.devnode->name);
		atomisp_reset_event(asd);
			"send reset event to %s\n", isp->asd.subdev.devnode->name);
		atomisp_reset_event(&isp->asd);
	}

	/* clear irq */
@@ -1057,25 +1007,20 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
	atomisp_reset(isp);
	isp->isp_timeout = false;

	for (i = 0; i < isp->num_of_streams; i++) {
		struct atomisp_sub_device *asd = &isp->asd[i];

		if (!stream_restart[i])
			continue;
	if (stream_restart) {
		atomisp_css_input_set_mode(&isp->asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);

		atomisp_css_input_set_mode(asd, IA_CSS_INPUT_MODE_BUFFERED_SENSOR);

		css_pipe_id = atomisp_get_css_pipe_id(asd);
		if (atomisp_css_start(asd, css_pipe_id, true)) {
		css_pipe_id = atomisp_get_css_pipe_id(&isp->asd);
		if (atomisp_css_start(&isp->asd, css_pipe_id, true)) {
			dev_warn(isp->dev,
				 "start SP failed, so do not set streaming to be enable!\n");
		} else {
			spin_lock_irqsave(&isp->lock, flags);
			asd->streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
			isp->asd.streaming = ATOMISP_DEVICE_STREAMING_ENABLED;
			spin_unlock_irqrestore(&isp->lock, flags);
		}

		atomisp_csi2_configure(asd);
		atomisp_csi2_configure(&isp->asd);
	}

	atomisp_css_irq_enable(isp, IA_CSS_IRQ_INFO_CSS_RECEIVER_SOF,
@@ -1084,27 +1029,20 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout)
	if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_AUTO, true) < 0)
		dev_dbg(isp->dev, "DFS auto failed while recovering!\n");

	for (i = 0; i < isp->num_of_streams; i++) {
		struct atomisp_sub_device *asd;

		asd = &isp->asd[i];

		if (!stream_restart[i])
			continue;

	if (stream_restart) {
		/*
		 * dequeueing buffers is not needed. CSS will recycle
		 * buffers that it has.
		 */
		atomisp_flush_bufs_and_wakeup(asd);
		atomisp_flush_bufs_and_wakeup(&isp->asd);

		/* Requeue unprocessed per-frame parameters. */
		atomisp_recover_params_queue(&asd->video_out_capture);
		atomisp_recover_params_queue(&asd->video_out_preview);
		atomisp_recover_params_queue(&asd->video_out_video_capture);
		atomisp_recover_params_queue(&isp->asd.video_out_capture);
		atomisp_recover_params_queue(&isp->asd.video_out_preview);
		atomisp_recover_params_queue(&isp->asd.video_out_video_capture);

		ret = v4l2_subdev_call(
			  isp->inputs[asd->input_curr].camera, video,
			  isp->inputs[isp->asd.input_curr].camera, video,
			  s_stream, 1);
		if (ret)
			dev_warn(isp->dev,
@@ -1164,10 +1102,6 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
{
	struct atomisp_device *isp = isp_ptr;
	unsigned long flags;
	bool frame_done_found[MAX_STREAM_NUM] = {0};
	bool css_pipe_done[MAX_STREAM_NUM] = {0};
	unsigned int i;
	struct atomisp_sub_device *asd;

	dev_dbg(isp->dev, ">%s\n", __func__);

@@ -1206,15 +1140,11 @@ irqreturn_t atomisp_isr_thread(int irq, void *isp_ptr)
	 * time, instead, dequue one and process one, then another
	 */
	mutex_lock(&isp->mutex);
	if (atomisp_css_isr_thread(isp, frame_done_found, css_pipe_done))
	if (atomisp_css_isr_thread(isp))
		goto out;

	for (i = 0; i < isp->num_of_streams; i++) {
		asd = &isp->asd[i];
		if (asd->streaming != ATOMISP_DEVICE_STREAMING_ENABLED)
			continue;
		atomisp_setup_flash(asd);
	}
	if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_ENABLED)
		atomisp_setup_flash(&isp->asd);
out:
	mutex_unlock(&isp->mutex);
	dev_dbg(isp->dev, "<%s\n", __func__);
+1 −3
Original line number Diff line number Diff line
@@ -416,9 +416,7 @@ int atomisp_css_get_dis_stat(struct atomisp_sub_device *asd,

int atomisp_css_update_stream(struct atomisp_sub_device *asd);

int atomisp_css_isr_thread(struct atomisp_device *isp,
			   bool *frame_done_found,
			   bool *css_pipe_done);
int atomisp_css_isr_thread(struct atomisp_device *isp);

bool atomisp_css_valid_sof(struct atomisp_device *isp);

+35 −54
Original line number Diff line number Diff line
@@ -3393,41 +3393,33 @@ void atomisp_css_morph_table_free(struct ia_css_morph_table *table)
	ia_css_morph_table_free(table);
}

static struct atomisp_sub_device *__get_atomisp_subdev(
    struct ia_css_pipe *css_pipe,
static bool atomisp_css_isr_get_stream_id(struct ia_css_pipe *css_pipe,
					  struct atomisp_device *isp,
					  enum atomisp_input_stream_id *stream_id)
{
	int i, j, k;
	struct atomisp_sub_device *asd;
	struct atomisp_stream_env *stream_env;
	int i, j;

	for (i = 0; i < isp->num_of_streams; i++) {
		asd = &isp->asd[i];
		if (asd->streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
			continue;
		for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
			stream_env = &asd->stream_env[j];
			for (k = 0; k < IA_CSS_PIPE_ID_NUM; k++) {
				if (stream_env->pipes[k] &&
				    stream_env->pipes[k] == css_pipe) {
					*stream_id = j;
					return asd;
				}
	if (isp->asd.streaming == ATOMISP_DEVICE_STREAMING_DISABLED)
		return false;

	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
		stream_env = &isp->asd.stream_env[i];
		for (j = 0; j < IA_CSS_PIPE_ID_NUM; j++) {
			if (stream_env->pipes[j] && stream_env->pipes[j] == css_pipe) {
				*stream_id = i;
				return true;
			}
		}
	}

	return NULL;
	return false;
}

int atomisp_css_isr_thread(struct atomisp_device *isp,
			   bool *frame_done_found,
			   bool *css_pipe_done)
int atomisp_css_isr_thread(struct atomisp_device *isp)
{
	enum atomisp_input_stream_id stream_id = 0;
	struct atomisp_css_event current_event;
	struct atomisp_sub_device *asd;

	lockdep_assert_held(&isp->mutex);

@@ -3453,9 +3445,7 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,
			continue;
		}

		asd = __get_atomisp_subdev(current_event.event.pipe,
					   isp, &stream_id);
		if (!asd) {
		if (!atomisp_css_isr_get_stream_id(current_event.event.pipe, isp, &stream_id)) {
			if (current_event.event.type == IA_CSS_EVENT_TYPE_TIMER)
				dev_dbg(isp->dev,
					"event: Timer event.");
@@ -3466,56 +3456,53 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,
			continue;
		}

		atomisp_css_temp_pipe_to_pipe_id(asd, &current_event);
		atomisp_css_temp_pipe_to_pipe_id(&isp->asd, &current_event);
		switch (current_event.event.type) {
		case IA_CSS_EVENT_TYPE_OUTPUT_FRAME_DONE:
			dev_dbg(isp->dev, "event: Output frame done");
			frame_done_found[asd->index] = true;
			atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
			atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_OUTPUT_FRAME,
					 current_event.pipe, true, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_SECOND_OUTPUT_FRAME_DONE:
			dev_dbg(isp->dev, "event: Second output frame done");
			frame_done_found[asd->index] = true;
			atomisp_buf_done(asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
			atomisp_buf_done(&isp->asd, 0, IA_CSS_BUFFER_TYPE_SEC_OUTPUT_FRAME,
					 current_event.pipe, true, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_3A_STATISTICS_DONE:
			dev_dbg(isp->dev, "event: 3A stats frame done");
			atomisp_buf_done(asd, 0,
			atomisp_buf_done(&isp->asd, 0,
					 IA_CSS_BUFFER_TYPE_3A_STATISTICS,
					 current_event.pipe,
					 false, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_METADATA_DONE:
			dev_dbg(isp->dev, "event: metadata frame done");
			atomisp_buf_done(asd, 0,
			atomisp_buf_done(&isp->asd, 0,
					 IA_CSS_BUFFER_TYPE_METADATA,
					 current_event.pipe,
					 false, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_VF_OUTPUT_FRAME_DONE:
			dev_dbg(isp->dev, "event: VF output frame done");
			atomisp_buf_done(asd, 0,
			atomisp_buf_done(&isp->asd, 0,
					 IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME,
					 current_event.pipe, true, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_SECOND_VF_OUTPUT_FRAME_DONE:
			dev_dbg(isp->dev, "event: second VF output frame done");
			atomisp_buf_done(asd, 0,
			atomisp_buf_done(&isp->asd, 0,
					 IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME,
					 current_event.pipe, true, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_DIS_STATISTICS_DONE:
			dev_dbg(isp->dev, "event: dis stats frame done");
			atomisp_buf_done(asd, 0,
			atomisp_buf_done(&isp->asd, 0,
					 IA_CSS_BUFFER_TYPE_DIS_STATISTICS,
					 current_event.pipe,
					 false, stream_id);
			break;
		case IA_CSS_EVENT_TYPE_PIPELINE_DONE:
			dev_dbg(isp->dev, "event: pipeline done");
			css_pipe_done[asd->index] = true;
			break;
		case IA_CSS_EVENT_TYPE_ACC_STAGE_COMPLETE:
			dev_warn(isp->dev, "unexpected event: acc stage done");
@@ -3532,24 +3519,18 @@ int atomisp_css_isr_thread(struct atomisp_device *isp,

bool atomisp_css_valid_sof(struct atomisp_device *isp)
{
	unsigned int i, j;
	unsigned int i;

	/* Loop for each css stream */
	for (i = 0; i < isp->num_of_streams; i++) {
		struct atomisp_sub_device *asd = &isp->asd[i];
	/* Loop for each css vc stream */
		for (j = 0; j < ATOMISP_INPUT_STREAM_NUM; j++) {
			if (!asd->stream_env[j].stream)
	for (i = 0; i < ATOMISP_INPUT_STREAM_NUM; i++) {
		if (!isp->asd.stream_env[i].stream)
			continue;

			dev_dbg(isp->dev,
				"stream #%d: mode: %d\n", j,
				asd->stream_env[j].stream_config.mode);
			if (asd->stream_env[j].stream_config.mode ==
			    IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
		dev_dbg(isp->dev, "stream #%d: mode: %d\n",
			i, isp->asd.stream_env[i].stream_config.mode);
		if (isp->asd.stream_env[i].stream_config.mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR)
			return false;
	}
	}

	return true;
}
+1 −6
Original line number Diff line number Diff line
@@ -594,12 +594,7 @@ static unsigned int atomisp_subdev_users(struct atomisp_sub_device *asd)

unsigned int atomisp_dev_users(struct atomisp_device *isp)
{
	unsigned int i, sum;

	for (i = 0, sum = 0; i < isp->num_of_streams; i++)
		sum += atomisp_subdev_users(&isp->asd[i]);

	return sum;
	return atomisp_subdev_users(&isp->asd);
}

static int atomisp_open(struct file *file)
+2 −15
Original line number Diff line number Diff line
@@ -48,8 +48,6 @@
	(((isp)->media_dev.hw_revision & ATOMISP_HW_REVISION_MASK) == \
	 ((rev) << ATOMISP_HW_REVISION_SHIFT))

#define MAX_STREAM_NUM	2

#define ATOMISP_PCI_DEVICE_SOC_MASK	0xfff8
/* MRFLD with 0x1178: ISP freq can burst to 457MHz */
#define ATOMISP_PCI_DEVICE_SOC_MRFLD	0x1178
@@ -181,6 +179,7 @@ struct atomisp_device {
	struct device *dev;
	struct v4l2_device v4l2_dev;
	struct media_device media_dev;
	struct atomisp_sub_device asd;
	struct atomisp_platform_data *pdata;
	void *mmu_l1_base;
	void __iomem *base;
@@ -190,18 +189,6 @@ struct atomisp_device {
	struct pm_qos_request pm_qos;
	s32 max_isr_latency;

	/*
	 * ISP modules
	 * Multiple streams are represents by multiple
	 * atomisp_sub_device instances
	 */
	struct atomisp_sub_device *asd;
	/*
	 * this will be assigned dyanamically.
	 * For Merr/BTY(ISP2400), 2 streams are supported.
	 */
	unsigned int num_of_streams;

	struct atomisp_mipi_csi2_device csi2_port[ATOMISP_CAMERA_NR_PORTS];
	struct atomisp_tpg_device tpg;

@@ -222,7 +209,7 @@ struct atomisp_device {
	bool isp_fatal_error;
	struct work_struct assert_recovery_work;

	spinlock_t lock; /* Protects asd[i].streaming */
	spinlock_t lock; /* Protects asd.streaming */

	bool need_gfx_throttle;

Loading