Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,4 +5,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +61 −1 Original line number Diff line number Diff line Loading @@ -75,4 +75,64 @@ int32_t cam_cci_i2c_poll(struct cam_sensor_cci_client *client, enum camera_sensor_i2c_type addr_type, uint32_t delay_ms); #endif /* _CAM_SENSOR_I2C_H_ */ /** * cam_qup_i2c_read : QUP based i2c read * @client : QUP I2C client structure * @data : I2C data * @addr_type : I2c address type * @data_type : I2C data type * * This API handles QUP I2C read */ int32_t cam_qup_i2c_read(struct i2c_client *client, uint32_t addr, uint32_t *data, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type); /** * cam_qup_i2c_read_seq : QUP based I2C sequential read * @client : QUP I2C client structure * @data : I2C data * @addr_type : I2c address type * @num_bytes : number of bytes to read * This API handles QUP I2C Sequential read */ int32_t cam_qup_i2c_read_seq(struct i2c_client *client, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_byte); /** * cam_qup_i2c_poll : QUP based I2C poll operation * @client : QUP I2C client structure * @addr : I2C address * @data : I2C data * @data_mask : I2C data mask * @data_type : I2C data type * @addr_type : I2C addr type * @delay_ms : Delay in milli seconds * * This API implements QUP based I2C poll */ int32_t cam_qup_i2c_poll(struct i2c_client *client, uint32_t addr, uint16_t data, uint16_t data_mask, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type, uint32_t delay_ms); /** * cam_qup_i2c_write_table : QUP based I2C write random * @client : QUP I2C client structure * @write_setting : I2C register settings * * This API handles QUP I2C random write */ int32_t cam_qup_i2c_write_table( struct camera_io_master *client, struct cam_sensor_i2c_reg_setting *write_setting); #endif /*_CAM_SENSOR_I2C_H*/ drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c +10 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,10 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_poll(io_master_info->cci_client, addr, data, mask, data_type, addr_type, delay_ms); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_poll(io_master_info->client, addr, data, data_mask, addr_type, data_type, delay_ms); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading @@ -49,6 +53,9 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_read(io_master_info->cci_client, addr, data, addr_type, data_type); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_read(io_master_info->client, addr, data, addr_type, data_type); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading @@ -68,6 +75,9 @@ int32_t camera_io_dev_write(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_write_table(io_master_info, write_setting); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_write_table(io_master_info, write_setting); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h +16 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct camera_io_master { * @io_master_info: I2C/SPI master information * @addr: I2C address * @data: I2C data * @addr_type: I2C addr type * @addr_type: I2C addr_type * @data_type: I2C data type * * This API abstracts read functionality based on master type Loading @@ -48,6 +48,21 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type); /** * @io_master_info: I2C/SPI master information * @addr: I2C address * @data: I2C data * @addr_type: I2C addr type * @num_bytes: number of bytes * * This API abstracts sequential read functionality based on master type */ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_bytes); /** * @io_master_info: I2C/SPI master information * Loading drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c 0 → 100644 +361 −0 Original line number Diff line number Diff line /* Copyright (c) 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 * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cam_sensor_cmn_header.h" #include "cam_sensor_i2c.h" #include "cam_sensor_io.h" #define I2C_REG_DATA_MAX (8*1024) #define I2C_REG_MAX_BUF_SIZE 8 static int32_t cam_qup_i2c_rxdata( struct i2c_client *dev_client, unsigned char *rxdata, enum camera_sensor_i2c_type addr_type, int data_length) { int32_t rc = 0; uint16_t saddr = dev_client->addr >> 1; struct i2c_msg msgs[] = { { .addr = saddr, .flags = 0, .len = addr_type, .buf = rxdata, }, { .addr = saddr, .flags = I2C_M_RD, .len = data_length, .buf = rxdata, }, }; rc = i2c_transfer(dev_client->adapter, msgs, 2); if (rc < 0) pr_err("%s:failed 0x%x\n", __func__, saddr); return rc; } static int32_t cam_qup_i2c_txdata( struct camera_io_master *dev_client, unsigned char *txdata, int length) { int32_t rc = 0; uint16_t saddr = dev_client->client->addr >> 1; struct i2c_msg msg[] = { { .addr = saddr, .flags = 0, .len = length, .buf = txdata, }, }; rc = i2c_transfer(dev_client->client->adapter, msg, 1); if (rc < 0) pr_err("%s: failed 0x%x\n", __func__, saddr); return rc; } int32_t cam_qup_i2c_read(struct i2c_client *client, uint32_t addr, uint32_t *data, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { int32_t rc = -EINVAL; unsigned char *buf = NULL; if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { pr_err("ERR: %s Failed with addr/data_type verfication\n", __func__); return rc; } buf = kzalloc(addr_type + data_type, GFP_KERNEL); if (!buf) return -ENOMEM; if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = addr >> 8; buf[1] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = addr >> 16; buf[1] = addr >> 8; buf[2] = addr; } else { buf[0] = addr >> 24; buf[1] = addr >> 16; buf[2] = addr >> 8; buf[3] = addr; } rc = cam_qup_i2c_rxdata(client, buf, addr_type, data_type); if (rc < 0) { pr_err("%s fail\n", __func__); goto read_fail; } if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) *data = buf[0]; else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) *data = buf[0] << 8 | buf[1]; else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) *data = buf[0] << 16 | buf[1] << 8 | buf[2]; else *data = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; CDBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data); read_fail: kfree(buf); buf = NULL; return rc; } int32_t cam_qup_i2c_read_seq(struct i2c_client *client, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_byte) { int32_t rc = -EFAULT; unsigned char *buf = NULL; int i; if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { pr_err("ERR: %s Failed with addr_type verification\n", __func__); return rc; } if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) { pr_err("%s: Error num_byte:0x%x max supported:0x%x\n", __func__, num_byte, I2C_REG_DATA_MAX); return rc; } buf = kzalloc(addr_type + num_byte, GFP_KERNEL); if (!buf) return -ENOMEM; if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = addr >> BITS_PER_BYTE; buf[1] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = addr >> 16; buf[1] = addr >> 8; buf[2] = addr; } else { buf[0] = addr >> 24; buf[1] = addr >> 16; buf[2] = addr >> 8; buf[3] = addr; } rc = cam_qup_i2c_rxdata(client, buf, addr_type, num_byte); if (rc < 0) { pr_err("%s fail\n", __func__); goto read_seq_fail; } for (i = 0; i < num_byte; i++) data[i] = buf[i]; read_seq_fail: kfree(buf); buf = NULL; return rc; } static int32_t cam_qup_i2c_compare(struct i2c_client *client, uint32_t addr, uint32_t data, uint16_t data_mask, enum camera_sensor_i2c_type data_type, enum camera_sensor_i2c_type addr_type) { int32_t rc; uint32_t reg_data = 0; rc = cam_qup_i2c_read(client, addr, ®_data, addr_type, data_type); if (rc < 0) return rc; reg_data = reg_data & 0xFFFF; if (data != (reg_data & ~data_mask)) return I2C_COMPARE_MISMATCH; return I2C_COMPARE_MATCH; } int32_t cam_qup_i2c_poll(struct i2c_client *client, uint32_t addr, uint16_t data, uint16_t data_mask, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type, uint32_t delay_ms) { int32_t rc = 0; int i = 0; if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) { pr_err("%s:%d invalid delay = %d max_delay = %d\n", __func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS); return -EINVAL; } if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) return -EINVAL; for (i = 0; i < delay_ms; i++) { rc = cam_qup_i2c_compare(client, addr, data, data_mask, data_type, addr_type); if (rc == I2C_COMPARE_MATCH) return rc; usleep_range(1000, 1010); } /* If rc is MISMATCH then read is successful but poll is failure */ if (rc == I2C_COMPARE_MISMATCH) pr_err("%s:%d poll failed rc=%d(non-fatal)\n", __func__, __LINE__, rc); if (rc < 0) pr_err("%s:%d poll failed rc=%d\n", __func__, __LINE__, rc); return rc; } static int32_t cam_qup_i2c_write(struct camera_io_master *client, struct cam_sensor_i2c_reg_array *reg_setting, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { int32_t rc = 0; unsigned char buf[I2C_REG_MAX_BUF_SIZE]; uint8_t len = 0; CDBG("%s reg addr = 0x%x data type: %d\n", __func__, reg_setting->reg_addr, data_type); if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = reg_setting->reg_addr; CDBG("%s byte %d: 0x%x\n", __func__, len, buf[len]); len = 1; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = reg_setting->reg_addr >> 8; buf[1] = reg_setting->reg_addr; CDBG("%s byte %d: 0x%x\n", __func__, len, buf[len]); CDBG("%s byte %d: 0x%x\n", __func__, len+1, buf[len+1]); len = 2; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = reg_setting->reg_addr >> 16; buf[1] = reg_setting->reg_addr >> 8; buf[2] = reg_setting->reg_addr; len = 3; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { buf[0] = reg_setting->reg_addr >> 24; buf[1] = reg_setting->reg_addr >> 16; buf[2] = reg_setting->reg_addr >> 8; buf[3] = reg_setting->reg_addr; len = 4; } else { pr_err("%s: Invalid I2C addr type\n", __func__); return -EINVAL; } CDBG("Data: 0x%x\n", reg_setting->reg_data); if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[len] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); len += 1; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[len] = reg_setting->reg_data >> 8; buf[len+1] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); len += 2; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[len] = reg_setting->reg_data >> 16; buf[len + 1] = reg_setting->reg_data >> 8; buf[len + 2] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]); len += 3; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { buf[len] = reg_setting->reg_data >> 24; buf[len + 1] = reg_setting->reg_data >> 16; buf[len + 2] = reg_setting->reg_data >> 8; buf[len + 3] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]); CDBG("Byte %d: 0x%x\n", len+3, buf[len+3]); len += 4; } else { pr_err("%s: Invalid Data Type\n", __func__); return -EINVAL; } rc = cam_qup_i2c_txdata(client, buf, len); if (rc < 0) pr_err("%s fail\n", __func__); return rc; } int32_t cam_qup_i2c_write_table(struct camera_io_master *client, struct cam_sensor_i2c_reg_setting *write_setting) { int i; int32_t rc = -EINVAL; struct cam_sensor_i2c_reg_array *reg_setting; if (!client || !write_setting) return rc; if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) return rc; reg_setting = write_setting->reg_setting; for (i = 0; i < write_setting->size; i++) { CDBG("%s addr 0x%x data 0x%x\n", __func__, reg_setting->reg_addr, reg_setting->reg_data); rc = cam_qup_i2c_write(client, reg_setting, write_setting->addr_type, write_setting->data_type); if (rc < 0) break; reg_setting++; } if (write_setting->delay > 20) msleep(write_setting->delay); else if (write_setting->delay) usleep_range(write_setting->delay * 1000, (write_setting->delay * 1000) + 1000); return rc; } Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,4 +5,4 @@ ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci ccflags-y += -Idrivers/media/platform/msm/camera/cam_req_mgr obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_sensor_io.o cam_sensor_cci_i2c.o cam_sensor_qup_i2c.o
drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_i2c.h +61 −1 Original line number Diff line number Diff line Loading @@ -75,4 +75,64 @@ int32_t cam_cci_i2c_poll(struct cam_sensor_cci_client *client, enum camera_sensor_i2c_type addr_type, uint32_t delay_ms); #endif /* _CAM_SENSOR_I2C_H_ */ /** * cam_qup_i2c_read : QUP based i2c read * @client : QUP I2C client structure * @data : I2C data * @addr_type : I2c address type * @data_type : I2C data type * * This API handles QUP I2C read */ int32_t cam_qup_i2c_read(struct i2c_client *client, uint32_t addr, uint32_t *data, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type); /** * cam_qup_i2c_read_seq : QUP based I2C sequential read * @client : QUP I2C client structure * @data : I2C data * @addr_type : I2c address type * @num_bytes : number of bytes to read * This API handles QUP I2C Sequential read */ int32_t cam_qup_i2c_read_seq(struct i2c_client *client, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_byte); /** * cam_qup_i2c_poll : QUP based I2C poll operation * @client : QUP I2C client structure * @addr : I2C address * @data : I2C data * @data_mask : I2C data mask * @data_type : I2C data type * @addr_type : I2C addr type * @delay_ms : Delay in milli seconds * * This API implements QUP based I2C poll */ int32_t cam_qup_i2c_poll(struct i2c_client *client, uint32_t addr, uint16_t data, uint16_t data_mask, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type, uint32_t delay_ms); /** * cam_qup_i2c_write_table : QUP based I2C write random * @client : QUP I2C client structure * @write_setting : I2C register settings * * This API handles QUP I2C random write */ int32_t cam_qup_i2c_write_table( struct camera_io_master *client, struct cam_sensor_i2c_reg_setting *write_setting); #endif /*_CAM_SENSOR_I2C_H*/
drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c +10 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,10 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_poll(io_master_info->cci_client, addr, data, mask, data_type, addr_type, delay_ms); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_poll(io_master_info->client, addr, data, data_mask, addr_type, data_type, delay_ms); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading @@ -49,6 +53,9 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_read(io_master_info->cci_client, addr, data, addr_type, data_type); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_read(io_master_info->client, addr, data, addr_type, data_type); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading @@ -68,6 +75,9 @@ int32_t camera_io_dev_write(struct camera_io_master *io_master_info, if (io_master_info->master_type == CCI_MASTER) { return cam_cci_i2c_write_table(io_master_info, write_setting); } else if (io_master_info->master_type == I2C_MASTER) { return cam_qup_i2c_write_table(io_master_info, write_setting); } else { pr_err("%s:%d Invalid Comm. Master:%d\n", __func__, __LINE__, io_master_info->master_type); Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.h +16 −1 Original line number Diff line number Diff line Loading @@ -38,7 +38,7 @@ struct camera_io_master { * @io_master_info: I2C/SPI master information * @addr: I2C address * @data: I2C data * @addr_type: I2C addr type * @addr_type: I2C addr_type * @data_type: I2C data type * * This API abstracts read functionality based on master type Loading @@ -48,6 +48,21 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type); /** * @io_master_info: I2C/SPI master information * @addr: I2C address * @data: I2C data * @addr_type: I2C addr type * @num_bytes: number of bytes * * This API abstracts sequential read functionality based on master type */ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_bytes); /** * @io_master_info: I2C/SPI master information * Loading
drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c 0 → 100644 +361 −0 Original line number Diff line number Diff line /* Copyright (c) 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 * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "cam_sensor_cmn_header.h" #include "cam_sensor_i2c.h" #include "cam_sensor_io.h" #define I2C_REG_DATA_MAX (8*1024) #define I2C_REG_MAX_BUF_SIZE 8 static int32_t cam_qup_i2c_rxdata( struct i2c_client *dev_client, unsigned char *rxdata, enum camera_sensor_i2c_type addr_type, int data_length) { int32_t rc = 0; uint16_t saddr = dev_client->addr >> 1; struct i2c_msg msgs[] = { { .addr = saddr, .flags = 0, .len = addr_type, .buf = rxdata, }, { .addr = saddr, .flags = I2C_M_RD, .len = data_length, .buf = rxdata, }, }; rc = i2c_transfer(dev_client->adapter, msgs, 2); if (rc < 0) pr_err("%s:failed 0x%x\n", __func__, saddr); return rc; } static int32_t cam_qup_i2c_txdata( struct camera_io_master *dev_client, unsigned char *txdata, int length) { int32_t rc = 0; uint16_t saddr = dev_client->client->addr >> 1; struct i2c_msg msg[] = { { .addr = saddr, .flags = 0, .len = length, .buf = txdata, }, }; rc = i2c_transfer(dev_client->client->adapter, msg, 1); if (rc < 0) pr_err("%s: failed 0x%x\n", __func__, saddr); return rc; } int32_t cam_qup_i2c_read(struct i2c_client *client, uint32_t addr, uint32_t *data, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { int32_t rc = -EINVAL; unsigned char *buf = NULL; if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { pr_err("ERR: %s Failed with addr/data_type verfication\n", __func__); return rc; } buf = kzalloc(addr_type + data_type, GFP_KERNEL); if (!buf) return -ENOMEM; if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = addr >> 8; buf[1] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = addr >> 16; buf[1] = addr >> 8; buf[2] = addr; } else { buf[0] = addr >> 24; buf[1] = addr >> 16; buf[2] = addr >> 8; buf[3] = addr; } rc = cam_qup_i2c_rxdata(client, buf, addr_type, data_type); if (rc < 0) { pr_err("%s fail\n", __func__); goto read_fail; } if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) *data = buf[0]; else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) *data = buf[0] << 8 | buf[1]; else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) *data = buf[0] << 16 | buf[1] << 8 | buf[2]; else *data = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; CDBG("%s addr = 0x%x data: 0x%x\n", __func__, addr, *data); read_fail: kfree(buf); buf = NULL; return rc; } int32_t cam_qup_i2c_read_seq(struct i2c_client *client, uint32_t addr, uint8_t *data, enum camera_sensor_i2c_type addr_type, uint32_t num_byte) { int32_t rc = -EFAULT; unsigned char *buf = NULL; int i; if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) { pr_err("ERR: %s Failed with addr_type verification\n", __func__); return rc; } if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) { pr_err("%s: Error num_byte:0x%x max supported:0x%x\n", __func__, num_byte, I2C_REG_DATA_MAX); return rc; } buf = kzalloc(addr_type + num_byte, GFP_KERNEL); if (!buf) return -ENOMEM; if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = addr >> BITS_PER_BYTE; buf[1] = addr; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = addr >> 16; buf[1] = addr >> 8; buf[2] = addr; } else { buf[0] = addr >> 24; buf[1] = addr >> 16; buf[2] = addr >> 8; buf[3] = addr; } rc = cam_qup_i2c_rxdata(client, buf, addr_type, num_byte); if (rc < 0) { pr_err("%s fail\n", __func__); goto read_seq_fail; } for (i = 0; i < num_byte; i++) data[i] = buf[i]; read_seq_fail: kfree(buf); buf = NULL; return rc; } static int32_t cam_qup_i2c_compare(struct i2c_client *client, uint32_t addr, uint32_t data, uint16_t data_mask, enum camera_sensor_i2c_type data_type, enum camera_sensor_i2c_type addr_type) { int32_t rc; uint32_t reg_data = 0; rc = cam_qup_i2c_read(client, addr, ®_data, addr_type, data_type); if (rc < 0) return rc; reg_data = reg_data & 0xFFFF; if (data != (reg_data & ~data_mask)) return I2C_COMPARE_MISMATCH; return I2C_COMPARE_MATCH; } int32_t cam_qup_i2c_poll(struct i2c_client *client, uint32_t addr, uint16_t data, uint16_t data_mask, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type, uint32_t delay_ms) { int32_t rc = 0; int i = 0; if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) { pr_err("%s:%d invalid delay = %d max_delay = %d\n", __func__, __LINE__, delay_ms, MAX_POLL_DELAY_MS); return -EINVAL; } if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) return -EINVAL; for (i = 0; i < delay_ms; i++) { rc = cam_qup_i2c_compare(client, addr, data, data_mask, data_type, addr_type); if (rc == I2C_COMPARE_MATCH) return rc; usleep_range(1000, 1010); } /* If rc is MISMATCH then read is successful but poll is failure */ if (rc == I2C_COMPARE_MISMATCH) pr_err("%s:%d poll failed rc=%d(non-fatal)\n", __func__, __LINE__, rc); if (rc < 0) pr_err("%s:%d poll failed rc=%d\n", __func__, __LINE__, rc); return rc; } static int32_t cam_qup_i2c_write(struct camera_io_master *client, struct cam_sensor_i2c_reg_array *reg_setting, enum camera_sensor_i2c_type addr_type, enum camera_sensor_i2c_type data_type) { int32_t rc = 0; unsigned char buf[I2C_REG_MAX_BUF_SIZE]; uint8_t len = 0; CDBG("%s reg addr = 0x%x data type: %d\n", __func__, reg_setting->reg_addr, data_type); if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[0] = reg_setting->reg_addr; CDBG("%s byte %d: 0x%x\n", __func__, len, buf[len]); len = 1; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[0] = reg_setting->reg_addr >> 8; buf[1] = reg_setting->reg_addr; CDBG("%s byte %d: 0x%x\n", __func__, len, buf[len]); CDBG("%s byte %d: 0x%x\n", __func__, len+1, buf[len+1]); len = 2; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[0] = reg_setting->reg_addr >> 16; buf[1] = reg_setting->reg_addr >> 8; buf[2] = reg_setting->reg_addr; len = 3; } else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { buf[0] = reg_setting->reg_addr >> 24; buf[1] = reg_setting->reg_addr >> 16; buf[2] = reg_setting->reg_addr >> 8; buf[3] = reg_setting->reg_addr; len = 4; } else { pr_err("%s: Invalid I2C addr type\n", __func__); return -EINVAL; } CDBG("Data: 0x%x\n", reg_setting->reg_data); if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) { buf[len] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); len += 1; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) { buf[len] = reg_setting->reg_data >> 8; buf[len+1] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); len += 2; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) { buf[len] = reg_setting->reg_data >> 16; buf[len + 1] = reg_setting->reg_data >> 8; buf[len + 2] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]); len += 3; } else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) { buf[len] = reg_setting->reg_data >> 24; buf[len + 1] = reg_setting->reg_data >> 16; buf[len + 2] = reg_setting->reg_data >> 8; buf[len + 3] = reg_setting->reg_data; CDBG("Byte %d: 0x%x\n", len, buf[len]); CDBG("Byte %d: 0x%x\n", len+1, buf[len+1]); CDBG("Byte %d: 0x%x\n", len+2, buf[len+2]); CDBG("Byte %d: 0x%x\n", len+3, buf[len+3]); len += 4; } else { pr_err("%s: Invalid Data Type\n", __func__); return -EINVAL; } rc = cam_qup_i2c_txdata(client, buf, len); if (rc < 0) pr_err("%s fail\n", __func__); return rc; } int32_t cam_qup_i2c_write_table(struct camera_io_master *client, struct cam_sensor_i2c_reg_setting *write_setting) { int i; int32_t rc = -EINVAL; struct cam_sensor_i2c_reg_array *reg_setting; if (!client || !write_setting) return rc; if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX || (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID || write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))) return rc; reg_setting = write_setting->reg_setting; for (i = 0; i < write_setting->size; i++) { CDBG("%s addr 0x%x data 0x%x\n", __func__, reg_setting->reg_addr, reg_setting->reg_data); rc = cam_qup_i2c_write(client, reg_setting, write_setting->addr_type, write_setting->data_type); if (rc < 0) break; reg_setting++; } if (write_setting->delay > 20) msleep(write_setting->delay); else if (write_setting->delay) usleep_range(write_setting->delay * 1000, (write_setting->delay * 1000) + 1000); return rc; }