diff --git a/drivers/media/i2c/otp_eeprom.c b/drivers/media/i2c/otp_eeprom.c index 50c96e35f3fe..540e3f57fcd2 100644 --- a/drivers/media/i2c/otp_eeprom.c +++ b/drivers/media/i2c/otp_eeprom.c @@ -731,6 +731,58 @@ static void rkotp_read_af(struct eeprom_device *eeprom_dev, } +static void rkotp_read_qsc(struct eeprom_device *eeprom_dev, + struct otp_info *otp_ptr, + u32 base_addr) +{ + struct i2c_client *client = eeprom_dev->client; + struct device *dev = &eeprom_dev->client->dev; + u8 *qsc_calib = &otp_ptr->qsc_data.qsc_calib[0]; + u32 checksum = 0; + u32 temp = 0; + int i = 0; + int ret = 0; + + ret = read_reg_otp(client, base_addr, + 4, &otp_ptr->qsc_data.size); + checksum += otp_ptr->qsc_data.size; + base_addr += 4; + ret |= read_reg_otp(client, base_addr, + 2, &otp_ptr->qsc_data.version); + checksum += otp_ptr->qsc_data.version; + base_addr += 2; + ret |= read_reg_otp(client, base_addr, + 2, &otp_ptr->qsc_data.qsc_size); + checksum += otp_ptr->qsc_data.qsc_size; + base_addr += 2; + + ret |= read_reg_otp_buf(client, base_addr, RK_QSC_SIZE, qsc_calib); + base_addr += RK_QSC_SIZE; + + for (i = 0; i < RK_QSC_SIZE; i++) + checksum += qsc_calib[i]; + + for (i = 0; i < RK_QSC_RESERVED_SIZE; i++) { + ret |= read_reg_otp(client, base_addr, 1, &temp); + checksum += temp; + base_addr += 1; + } + + ret |= read_reg_otp(client, base_addr, + 1, &otp_ptr->qsc_data.checksum); + if ((checksum % 255 + 1) == otp_ptr->qsc_data.checksum && (!ret)) { + otp_ptr->qsc_data.flag = 0x01; + dev_info(dev, "qsc info:(data[0] 0x%x, checksum 0x%x)\n", + otp_ptr->qsc_data.qsc_calib[0], + (int)otp_ptr->qsc_data.checksum); + } else { + otp_ptr->qsc_data.flag = 0x00; + dev_info(dev, "qsc info: checksum err, checksum %d, reg_checksum %d\n", + (int)(checksum % 255 + 1), + (int)otp_ptr->qsc_data.checksum); + } +} + static int rkotp_read_data(struct eeprom_device *eeprom_dev) { struct i2c_client *client = eeprom_dev->client; @@ -780,6 +832,12 @@ static int rkotp_read_data(struct eeprom_device *eeprom_dev) base_addr + 1); base_addr += 0x20; break; + case RKOTP_QSC_ID: + rkotp_read_qsc(eeprom_dev, + otp_ptr, + base_addr + 1); + base_addr += 0x1010; + break; default: id = -1; break; diff --git a/drivers/media/i2c/otp_eeprom.h b/drivers/media/i2c/otp_eeprom.h index f284e6d59bb5..9ba9e76b64a5 100644 --- a/drivers/media/i2c/otp_eeprom.h +++ b/drivers/media/i2c/otp_eeprom.h @@ -58,6 +58,8 @@ #define RK_DCCMAP_SIZE 0x0200 #define RK_PDAF_RESERVED_SIZE 0x001e #define RK_AF_RESERVED_SIZE 0x0014 +#define RK_QSC_SIZE 0x1000 +#define RK_QSC_RESERVED_SIZE 0x0006 #define RKOTP_MAX_MODULE 0x0008 #define RKOTP_REG_START 0x0008//v1 0, v2 0x0008 @@ -66,6 +68,7 @@ #define RKOTP_LSC_ID 2 #define RKOTP_PDAF_ID 3 #define RKOTP_AF_ID 4 +#define RKOTP_QSC_ID 5 struct id_defination { u32 supplier_id; @@ -165,6 +168,15 @@ struct af_otp_info { u32 size; }; +struct qsc_otp_info { + u32 flag; + u32 version; + u32 qsc_size; + u8 qsc_calib[RK_QSC_SIZE]; + u32 checksum; + u32 size; +}; + struct otp_info { u32 flag; u32 total_checksum; @@ -174,6 +186,7 @@ struct otp_info { struct sfr_otp_info sfr_otp_data; struct pdaf_otp_info pdaf_data; struct af_otp_info af_data; + struct qsc_otp_info qsc_data; }; /* eeprom device structure */