Loading drivers/media/i2c/adv7481.c +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 Loading Loading @@ -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 { Loading Loading @@ -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) Loading @@ -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) { Loading Loading @@ -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, Loading @@ -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; } Loading Loading @@ -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}; Loading Loading @@ -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", Loading @@ -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; Loading @@ -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; Loading Loading @@ -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", Loading Loading @@ -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); } Loading Loading @@ -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 = Loading Loading
drivers/media/i2c/adv7481.c +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 Loading Loading @@ -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 { Loading Loading @@ -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) Loading @@ -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) { Loading Loading @@ -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, Loading @@ -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; } Loading Loading @@ -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}; Loading Loading @@ -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", Loading @@ -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; Loading @@ -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; Loading Loading @@ -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", Loading Loading @@ -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); } Loading Loading @@ -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 = Loading