From 9e195140a1141a10945b3be7fb2e126e9fd99f71 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Sat, 27 Aug 2022 09:31:25 +0000 Subject: [PATCH] media: i2c: otp_eeprom: add mutex & speedup otp read 1. add i2c buf read optimize otp read speed. 2. add mutex for otp read. Signed-off-by: Wang Panzhenzhuan Change-Id: I2609328bab3cad3ec10f9b1c5768e7c5f7f6e2fc --- drivers/media/i2c/otp_eeprom.c | 113 ++++++++++++++++++++++++++------- drivers/media/i2c/otp_eeprom.h | 1 + 2 files changed, 91 insertions(+), 23 deletions(-) diff --git a/drivers/media/i2c/otp_eeprom.c b/drivers/media/i2c/otp_eeprom.c index 64ae7e1fa5bc..2fb123ca72ac 100644 --- a/drivers/media/i2c/otp_eeprom.c +++ b/drivers/media/i2c/otp_eeprom.c @@ -9,8 +9,11 @@ * 3. add version control. * V0.0X01.0X02 * 1. fix otp info null issue. + * V0.0X01.0X03 + * 1. add buf read optimize otp read speed. + * 2. add mutex for otp read. */ - +//#define DEBUG #include #include #include @@ -24,7 +27,7 @@ #include #include "otp_eeprom.h" -#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x02) +#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03) #define DEVICE_NAME "otp_eeprom" static inline struct eeprom_device @@ -68,6 +71,33 @@ static int read_reg_otp(struct i2c_client *client, u16 reg, return 0; } +/* Read registers buffers at a time */ +static int read_reg_otp_buf(struct i2c_client *client, u16 reg, + unsigned int len, u8 *buf) +{ + struct i2c_msg msgs[2]; + __be16 reg_addr_be = cpu_to_be16(reg); + int ret; + + /* Write register address */ + msgs[0].addr = client->addr; + msgs[0].flags = 0; + msgs[0].len = 2; + msgs[0].buf = (u8 *)®_addr_be; + + /* Read data from register */ + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD; + msgs[1].len = len; + msgs[1].buf = buf; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + return 0; +} + static u8 get_vendor_flag(struct i2c_client *client) { u8 vendor_flag = 0; @@ -448,13 +478,19 @@ static void rkotp_read_lsc(struct eeprom_device *eeprom_dev, struct i2c_client *client = eeprom_dev->client; struct device *dev = &eeprom_dev->client->dev; u32 checksum = 0; - u32 temp = 0; + u8 *lsc_buf; int i = 0; int ret = 0; #ifdef DEBUG int w, h, j; #endif + lsc_buf = kzalloc(LSC_DATA_SIZE, GFP_KERNEL); + if (!lsc_buf) { + dev_err(dev, "%s ENOMEM!\n", __func__); + return; + } + ret = read_reg_otp(client, base_addr, 4, &otp_ptr->lsc_data.size); checksum += otp_ptr->lsc_data.size; @@ -463,12 +499,14 @@ static void rkotp_read_lsc(struct eeprom_device *eeprom_dev, 2, &otp_ptr->lsc_data.version); checksum += otp_ptr->lsc_data.version; base_addr += 2; + + ret |= read_reg_otp_buf(client, base_addr, + LSC_DATA_SIZE, lsc_buf); + base_addr += LSC_DATA_SIZE; + for (i = 0; i < LSC_DATA_SIZE; i++) { - ret |= read_reg_otp(client, base_addr, - 1, &temp); - otp_ptr->lsc_data.data[i] = temp; - checksum += temp; - base_addr += 1; + otp_ptr->lsc_data.data[i] = lsc_buf[i]; + checksum += lsc_buf[i]; } otp_ptr->lsc_data.table_size = LSC_DATA_SIZE; #ifdef DEBUG @@ -482,12 +520,15 @@ static void rkotp_read_lsc(struct eeprom_device *eeprom_dev, dev_info(dev, "\n"); } #endif + + memset(lsc_buf, 0, LSC_DATA_SIZE); + ret |= read_reg_otp_buf(client, base_addr, + RK_LSC_RESERVED_SIZE, lsc_buf); + for (i = 0; i < RK_LSC_RESERVED_SIZE; i++) { - ret |= read_reg_otp(client, base_addr, - 1, &temp); - checksum += temp; - base_addr += 1; + checksum += lsc_buf[i]; } + base_addr += RK_LSC_RESERVED_SIZE; ret |= read_reg_otp(client, base_addr, 1, &otp_ptr->lsc_data.checksum); if ((checksum % 255 + 1) == otp_ptr->lsc_data.checksum && (!ret)) { @@ -502,6 +543,7 @@ static void rkotp_read_lsc(struct eeprom_device *eeprom_dev, (int)(checksum % 255 + 1), (int)otp_ptr->lsc_data.checksum); } + kfree(lsc_buf); } static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, @@ -511,13 +553,19 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, struct i2c_client *client = eeprom_dev->client; struct device *dev = &eeprom_dev->client->dev; u32 checksum = 0; - u32 temp = 0; + u8 *pdaf_buf; int i = 0; int ret = 0; #ifdef DEBUG int w, h, j; #endif + pdaf_buf = kzalloc(RK_GAINMAP_SIZE, GFP_KERNEL); + if (!pdaf_buf) { + dev_err(dev, "%s ENOMEM!\n", __func__); + return; + } + ret = read_reg_otp(client, base_addr, 4, &otp_ptr->pdaf_data.size); checksum += otp_ptr->pdaf_data.size; @@ -534,11 +582,14 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, 1, &otp_ptr->pdaf_data.gainmap_height); checksum += otp_ptr->pdaf_data.gainmap_height; base_addr += 1; + + ret |= read_reg_otp_buf(client, base_addr, + RK_GAINMAP_SIZE, pdaf_buf); + base_addr += RK_GAINMAP_SIZE; + for (i = 0; i < RK_GAINMAP_SIZE; i++) { - ret |= read_reg_otp(client, base_addr, - 1, &otp_ptr->pdaf_data.gainmap[i]); + otp_ptr->pdaf_data.gainmap[i] = pdaf_buf[i]; checksum += otp_ptr->pdaf_data.gainmap[i]; - base_addr += 1; } #ifdef DEBUG w = 64; @@ -571,12 +622,17 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, 1, &otp_ptr->pdaf_data.dccmap_height); checksum += otp_ptr->pdaf_data.dccmap_height; base_addr += 1; + + memset(pdaf_buf, 0, RK_DCCMAP_SIZE); + ret |= read_reg_otp_buf(client, base_addr, + RK_DCCMAP_SIZE, pdaf_buf); + for (i = 0; i < RK_DCCMAP_SIZE; i++) { - ret |= read_reg_otp(client, base_addr, - 1, &otp_ptr->pdaf_data.dccmap[i]); + otp_ptr->pdaf_data.dccmap[i] = pdaf_buf[i]; checksum += otp_ptr->pdaf_data.dccmap[i]; - base_addr += 1; } + base_addr += RK_DCCMAP_SIZE; + #ifdef DEBUG w = 32; h = 16; @@ -592,12 +648,16 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, 1, &otp_ptr->pdaf_data.dccmap_checksum); checksum += otp_ptr->pdaf_data.dccmap_checksum; base_addr += 1; + + memset(pdaf_buf, 0, RK_PDAF_RESERVED_SIZE); + ret |= read_reg_otp_buf(client, base_addr, + RK_PDAF_RESERVED_SIZE, pdaf_buf); + for (i = 0; i < RK_PDAF_RESERVED_SIZE; i++) { - ret |= read_reg_otp(client, base_addr, - 1, &temp); - checksum += temp; - base_addr += 1; + checksum += pdaf_buf[i]; } + base_addr += RK_PDAF_RESERVED_SIZE; + ret |= read_reg_otp(client, base_addr, 1, &otp_ptr->pdaf_data.checksum); if ((checksum % 255 + 1) == otp_ptr->pdaf_data.checksum && (!ret)) { @@ -612,6 +672,7 @@ static void rkotp_read_pdaf(struct eeprom_device *eeprom_dev, (int)(checksum % 255 + 1), (int)otp_ptr->pdaf_data.checksum); } + kfree(pdaf_buf); } static void rkotp_read_af(struct eeprom_device *eeprom_dev, @@ -738,6 +799,7 @@ static int otp_read(struct eeprom_device *eeprom_dev) u8 vendor_flag = 0; struct i2c_client *client = eeprom_dev->client; + mutex_lock(&eeprom_dev->mutex); vendor_flag = get_vendor_flag(client); if (vendor_flag == 0x80) otp_read_data(eeprom_dev); @@ -745,8 +807,11 @@ static int otp_read(struct eeprom_device *eeprom_dev) rkotp_read_data(eeprom_dev); else { dev_warn(&client->dev, "no vendor flag infos!\n"); + mutex_unlock(&eeprom_dev->mutex); return -1; } + + mutex_unlock(&eeprom_dev->mutex); return 0; } @@ -973,6 +1038,7 @@ static int eeprom_probe(struct i2c_client *client, dev_err(&client->dev, "Probe failed\n"); return -ENOMEM; } + mutex_init(&eeprom_dev->mutex); v4l2_i2c_subdev_init(&eeprom_dev->sd, client, &eeprom_ops); eeprom_dev->client = client; @@ -994,6 +1060,7 @@ static int eeprom_remove(struct i2c_client *client) struct eeprom_device *eeprom_dev = sd_to_eeprom(sd); kfree(eeprom_dev->otp); + mutex_destroy(&eeprom_dev->mutex); pm_runtime_disable(&client->dev); eeprom_subdev_cleanup(eeprom_dev); eeprom_proc_cleanup(eeprom_dev); diff --git a/drivers/media/i2c/otp_eeprom.h b/drivers/media/i2c/otp_eeprom.h index 83c84a570114..503d27741936 100644 --- a/drivers/media/i2c/otp_eeprom.h +++ b/drivers/media/i2c/otp_eeprom.h @@ -182,6 +182,7 @@ struct eeprom_device { struct otp_info *otp; struct proc_dir_entry *procfs; char name[128]; + struct mutex mutex; }; #endif /* OTP_EEPROM_HEAD_H */