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

Commit 0943aa14 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "adv7481: Fix interrupt handling"

parents 0b461af0 34057087
Loading
Loading
Loading
Loading
+149 −109
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -61,6 +61,7 @@
#define MAX_DEFAULT_PIX_CLK_HZ  74240000

#define ONE_MHZ_TO_HZ		1000000
#define I2C_BLOCK_WRITE_SIZE    1024

enum adv7481_gpio_t {

@@ -263,6 +264,14 @@ static int32_t adv7481_cci_i2c_write(struct msm_camera_i2c_client *i2c_client,
				*data, data_type);
}

static int32_t adv7481_cci_i2c_write_seq(
	struct msm_camera_i2c_client *i2c_client,
	uint8_t reg, const uint8_t *data, uint32_t size)
{
	return i2c_client->i2c_func_tbl->i2c_write_seq(i2c_client, reg,
				(uint8_t *)data, size);
}

static int32_t adv7481_cci_i2c_read(struct msm_camera_i2c_client *i2c_client,
	uint8_t reg, uint16_t *data,
	enum msm_camera_i2c_data_type data_type)
@@ -287,6 +296,20 @@ static int32_t adv7481_wr_byte(struct msm_camera_i2c_client *c_i2c_client,
	return ret;
}

static int32_t adv7481_wr_block(struct msm_camera_i2c_client *c_i2c_client,
	uint8_t sid, uint8_t reg, const uint8_t *data, uint32_t size)
{
	int ret = 0;

	c_i2c_client->cci_client->sid = sid;

	ret = adv7481_cci_i2c_write_seq(c_i2c_client, reg, data, size);
	if (ret < 0)
		pr_err("Error %d writing cci i2c block data\n", ret);

	return ret;
}

static uint8_t adv7481_rd_byte(struct msm_camera_i2c_client *c_i2c_client,
	uint8_t sid, uint8_t reg)
{
@@ -387,6 +410,8 @@ static int adv7481_set_edid(struct adv7481_state *state)
	int i;
	int ret = 0;
	uint8_t edid_state;
	uint32_t data_left = 0;
	uint32_t start_pos;

	/* Enable Manual Control of EDID on Port A */
	ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_rep_addr, 0x74,
@@ -407,10 +432,20 @@ static int adv7481_set_edid(struct adv7481_state *state)
	pr_debug("%s: Readback EDID enable state: 0x%x\n", __func__,
			edid_state);

	for (i = 0; i < ADV7481_EDID_SIZE; i++) {
		ret |= adv7481_wr_byte(&state->i2c_client,
			state->i2c_edid_addr, i, adv7481_default_edid_data[i]);
	}
	for (i = 0; i < ADV7481_EDID_SIZE && !ret; i += I2C_BLOCK_WRITE_SIZE)
		ret |= adv7481_wr_block(&state->i2c_client,
			state->i2c_edid_addr,
			i, &adv7481_default_edid_data[i],
			I2C_BLOCK_WRITE_SIZE);

	data_left = ADV7481_EDID_SIZE % I2C_BLOCK_WRITE_SIZE;
	start_pos = ADV7481_EDID_SIZE - data_left;
	if (data_left && !ret)
		ret |= adv7481_wr_block(&state->i2c_client,
			state->i2c_edid_addr,
			start_pos,
			&adv7481_default_edid_data[start_pos],
			data_left);

	return ret;
}
@@ -497,6 +532,7 @@ static void adv7481_irq_delay_work(struct work_struct *work)
			state->device_num, int_raw_status);
	state->cec_detected = ADV_REG_GETFIELD(int_raw_status, IO_INT_CEC_ST);

	while (int_raw_status) {
		if (ADV_REG_GETFIELD(int_raw_status, IO_INTRQ1_RAW)) {
			int lock_status = -1;
			struct v4l2_event event = {0};
@@ -529,13 +565,15 @@ static void adv7481_irq_delay_work(struct work_struct *work)
					state->i2c_sdp_addr, SDP_RW_MAP_REG,
					0x01);
				sdp_sts = adv7481_rd_byte(&state->i2c_client,
				state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR);
					state->i2c_sdp_addr,
					SDP_RO_MAIN_STATUS1_ADDR);
				pr_debug("%s: dev: %d got sdp status: 0x%x\n",
					__func__, state->device_num, sdp_sts);
				adv7481_wr_byte(&state->i2c_client,
					state->i2c_sdp_addr, SDP_RW_MAP_REG,
					0x00);
			if (ADV_REG_GETFIELD(sdp_sts, SDP_RO_MAIN_IN_LOCK)) {
				if (ADV_REG_GETFIELD(sdp_sts,
					SDP_RO_MAIN_IN_LOCK)) {
					lock_status = 0;
					pr_debug(
					"%s: set lock_status SDP_IN_LOCK:0x%x\n",
@@ -556,7 +594,8 @@ static void adv7481_irq_delay_work(struct work_struct *work)
					state->i2c_sdp_addr, SDP_RW_MAP_REG,
					0x00);
			} else {
			if (ADV_REG_GETFIELD(int_status, IO_CP_LOCK_CP_ST) &&
				if (ADV_REG_GETFIELD(int_status,
						IO_CP_LOCK_CP_ST) &&
					ADV_REG_GETFIELD(raw_status,
						IO_CP_LOCK_CP_RAW)) {
					lock_status = 0;
@@ -564,7 +603,8 @@ static void adv7481_irq_delay_work(struct work_struct *work)
					"%s: set lock_status IO_CP_LOCK_CP_RAW:0x%x\n",
					__func__, lock_status);
				}
			if (ADV_REG_GETFIELD(int_status, IO_CP_UNLOCK_CP_ST) &&
				if (ADV_REG_GETFIELD(int_status,
						IO_CP_UNLOCK_CP_ST) &&
					ADV_REG_GETFIELD(raw_status,
						IO_CP_UNLOCK_CP_RAW)) {
					lock_status = 1;
@@ -603,6 +643,9 @@ static void adv7481_irq_delay_work(struct work_struct *work)
				state->i2c_io_addr,
				IO_HDMI_LVL_RAW_STATUS_3_ADDR);

			adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
				IO_HDMI_LVL_INT_CLEAR_3_ADDR, int_status);

			pr_debug("%s: dev: %d got hdmi lvl int status 3: 0x%x\n",
				__func__, state->device_num, int_status);
			pr_debug("%s: dev: %d got hdmi lvl raw status 3: 0x%x\n",
@@ -637,14 +680,10 @@ static void adv7481_irq_delay_work(struct work_struct *work)
				}
			}
		}
	/* Clear all other interrupts */
	adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
		IO_HDMI_LVL_INT_CLEAR_1_ADDR, 0xFF);
	adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
		IO_HDMI_LVL_INT_CLEAR_2_ADDR, 0xFF);
	adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
		IO_HDMI_LVL_INT_CLEAR_3_ADDR, 0xFF);

		int_raw_status = adv7481_rd_byte(&state->i2c_client,
				state->i2c_io_addr,
				IO_REG_INT_RAW_STATUS_ADDR);
	}
	mutex_unlock(&state->mutex);
}

@@ -2158,6 +2197,7 @@ static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = {
	.i2c_read = msm_camera_cci_i2c_read,
	.i2c_read_seq = msm_camera_cci_i2c_read_seq,
	.i2c_write = msm_camera_cci_i2c_write,
	.i2c_write_seq = msm_camera_cci_i2c_write_seq,
	.i2c_write_table = msm_camera_cci_i2c_write_table,
	.i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
	.i2c_write_table_w_microdelay =