Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020 Rockchip Electronics Co., Ltd.
/*
* otp_eeprom driver
*
* V0.0X01.0X01
* 1. fix table_size.
* 2. fix ioctl return value.
* 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 <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/proc_fs.h>
#include <linux/rk-camera-module.h>
#include <linux/sem.h>
#include <linux/seq_file.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <linux/version.h>
#include "otp_eeprom.h"
#define DRIVER_VERSION KERNEL_VERSION(0, 0x01, 0x03)
#define DEVICE_NAME "otp_eeprom"
static inline struct eeprom_device
<------>*sd_to_eeprom(struct v4l2_subdev *subdev)
{
<------>return container_of(subdev, struct eeprom_device, sd);
}
/* Read registers up to 4 at a time */
static int read_reg_otp(struct i2c_client *client, u16 reg,
<------>unsigned int len, u32 *val)
{
<------>struct i2c_msg msgs[2];
<------>u8 *data_be_p;
<------>__be32 data_be = 0;
<------>__be16 reg_addr_be = cpu_to_be16(reg);
<------>int ret;
<------>if (len > 4 || !len)
<------><------>return -EINVAL;
<------>data_be_p = (u8 *)&data_be;
<------>/* Write register address */
<------>msgs[0].addr = client->addr;
<------>msgs[0].flags = 0;
<------>msgs[0].len = 2;
<------>msgs[0].buf = (u8 *)&reg_addr_be;
<------>/* Read data from register */
<------>msgs[1].addr = client->addr;
<------>msgs[1].flags = I2C_M_RD;
<------>msgs[1].len = len;
<------>msgs[1].buf = &data_be_p[4 - len];
<------>ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
<------>if (ret != ARRAY_SIZE(msgs))
<------><------>return -EIO;
<------>*val = be32_to_cpu(data_be);
<------>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 *)&reg_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;
<------>u8 vendor[9];
<------>int i = 0;
<------>u32 temp = 0;
<------>for (i = 0; i < 8; i++) {
<------><------>read_reg_otp(client, INFO_FLAG_REG + i, 1, &temp);
<------><------>vendor[i] = (u8)temp;
<------>}
<------>vendor[8] = 0;
<------>if (strcmp(vendor, "ROCKCHIP") == 0)
<------><------>vendor_flag |= 0x40;
<------>else
<------><------>vendor_flag |= 0x80;
<------>return vendor_flag;
}
static int otp_read_data(struct eeprom_device *eeprom_dev)
{
<------>struct i2c_client *client = eeprom_dev->client;
<------>int i;
<------>struct otp_info *otp_ptr;
<------>struct device *dev = &eeprom_dev->client->dev;
<------>int ret = 0;
<------>u32 temp = 0;
<------>otp_ptr = kzalloc(sizeof(*otp_ptr), GFP_KERNEL);
<------>if (!otp_ptr)
<------><------>return -ENOMEM;
<------>/* OTP base information*/
<------>ret = read_reg_otp(client, INFO_FLAG_REG,
<------><------>1, &otp_ptr->basic_data.flag);
<------>if (otp_ptr->basic_data.flag == 0x01) {
<------><------>ret |= read_reg_otp(client, INFO_ID_REG,
<------><------><------>1, &otp_ptr->basic_data.id.supplier_id);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 1,
<------><------><------>1, &otp_ptr->basic_data.id.year);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 2,
<------><------><------>1, &otp_ptr->basic_data.id.month);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 3,
<------><------><------>1, &otp_ptr->basic_data.id.day);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 4,
<------><------><------>1, &otp_ptr->basic_data.id.sensor_id);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 5,
<------><------><------>1, &otp_ptr->basic_data.id.lens_id);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 6,
<------><------><------>1, &otp_ptr->basic_data.id.vcm_id);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 7,
<------><------><------>1, &otp_ptr->basic_data.id.driver_ic_id);
<------><------>ret |= read_reg_otp(client, INFO_ID_REG + 8,
<------><------><------>1, &otp_ptr->basic_data.id.color_temperature_id);
<------><------>for (i = 0; i < SMARTISAN_PN_SIZE; i++) {
<------><------><------>ret |= read_reg_otp(client, SMARTISAN_PN_REG + i,
<------><------><------><------>1, &temp);
<------><------><------>otp_ptr->basic_data.smartisan_pn[i] = temp;
<------><------>}
<------><------>for (i = 0; i < MOUDLE_ID_SIZE; i++) {
<------><------><------>ret |= read_reg_otp(client, MOUDLE_ID_REG + i,
<------><------><------><------>1, &temp);
<------><------><------><------>otp_ptr->basic_data.modul_id[i] = temp;
<------><------>}
<------><------>ret |= read_reg_otp(client, MIRROR_FLIP_REG,
<------><------><------>1, &otp_ptr->basic_data.mirror_flip);
<------><------>ret |= read_reg_otp(client, FULL_SIZE_WIGHT_REG,
<------><------><------>2, &temp);
<------><------>otp_ptr->basic_data.size.width = temp;
<------><------>ret |= read_reg_otp(client, FULL_SIZE_HEIGHT_REG,
<------><------><------>2, &temp);
<------><------>otp_ptr->basic_data.size.height = temp;
<------><------>ret |= read_reg_otp(client, INFO_CHECKSUM_REG,
<------><------><------>1, &otp_ptr->basic_data.checksum);
<------><------>dev_dbg(dev, "fasic info: supplier_id(0x%x) lens(0x%x) time(%d_%d_%d)\n",
<------><------><------>otp_ptr->basic_data.id.supplier_id,
<------><------><------>otp_ptr->basic_data.id.lens_id,
<------><------><------>otp_ptr->basic_data.id.year,
<------><------><------>otp_ptr->basic_data.id.month,
<------><------><------>otp_ptr->basic_data.id.day);
<------><------>if (ret)
<------><------><------>goto err;
<------>}
<------>/* OTP WB calibration data */
<------>ret = read_reg_otp(client, AWB_FLAG_REG,
<------><------>1, &otp_ptr->awb_data.flag);
<------>if (otp_ptr->awb_data.flag == 0x01) {
<------><------>ret |= read_reg_otp(client, AWB_VERSION_REG,
<------><------><------>1, &otp_ptr->awb_data.version);
<------><------>ret |= read_reg_otp(client, CUR_R_REG,
<------><------><------>2, &otp_ptr->awb_data.r_ratio);
<------><------>ret |= read_reg_otp(client, CUR_B_REG,
<------><------><------>2, &otp_ptr->awb_data.b_ratio);
<------><------>ret |= read_reg_otp(client, CUR_G_REG,
<------><------><------>2, &otp_ptr->awb_data.g_ratio);
<------><------>ret |= read_reg_otp(client, GOLDEN_R_REG,
<------><------><------>2, &otp_ptr->awb_data.r_golden);
<------><------>ret |= read_reg_otp(client, GOLDEN_B_REG,
<------><------><------>2, &otp_ptr->awb_data.b_golden);
<------><------>ret |= read_reg_otp(client, GOLDEN_G_REG,
<------><------><------>2, &otp_ptr->awb_data.g_golden);
<------><------>ret |= read_reg_otp(client, AWB_CHECKSUM_REG,
<------><------><------>1, &otp_ptr->awb_data.checksum);
<------><------>dev_dbg(dev, "awb version:0x%x\n",
<------><------><------>otp_ptr->awb_data.version);
<------><------>if (ret)
<------><------><------>goto err;
<------>}
<------>/* OTP LSC calibration data */
<------>ret = read_reg_otp(client, LSC_FLAG_REG,
<------><------>1, &otp_ptr->lsc_data.flag);
<------>if (otp_ptr->lsc_data.flag == 0x01) {
<------><------>ret |= read_reg_otp(client, LSC_VERSION_REG,
<------><------><------>1, &otp_ptr->lsc_data.version);
<------><------>ret |= read_reg_otp(client, LSC_TABLE_SIZE_REG,
<------><------><------>2, &temp);
<------><------>otp_ptr->lsc_data.table_size = temp;
<------><------>for (i = 0; i < LSC_DATA_SIZE; i++) {
<------><------><------>ret |= read_reg_otp(client, LSC_DATA_START_REG + i,
<------><------><------><------>1, &temp);
<------><------><------>otp_ptr->lsc_data.data[i] = temp;
<------><------>}
<------><------>ret |= read_reg_otp(client, LSC_CHECKSUM_REG,
<------><------><------>1, &otp_ptr->lsc_data.checksum);
<------><------>dev_dbg(dev, "lsc cur:(version 0x%x, table_size 0x%x checksum 0x%x)\n",
<------><------><------>otp_ptr->lsc_data.version,
<------><------><------>otp_ptr->lsc_data.table_size,
<------><------><------>otp_ptr->lsc_data.checksum);
<------><------>if (ret)
<------><------><------>goto err;
<------>}
<------>/* OTP sfr calibration data */
<------>ret = read_reg_otp(client, LSC_FLAG_REG,
<------><------>1, &otp_ptr->sfr_otp_data.flag);
<------>if (otp_ptr->sfr_otp_data.flag == 0x01) {
<------><------>ret |= read_reg_otp(client, SFR_EQUIQ_NUM_REG,
<------><------><------>1, &otp_ptr->sfr_otp_data.equip_num);
<------><------>ret |= read_reg_otp(client, SFR_C_HOR_REG,
<------><------><------>2, &otp_ptr->sfr_otp_data.center_horizontal);
<------><------>ret |= read_reg_otp(client, SFR_C_VER_REG,
<------><------><------>2, &otp_ptr->sfr_otp_data.center_vertical);
<------><------>for (i = 0; i < 3; i++) {
<------><------><------>ret |= read_reg_otp(client, SFR_TOP_L_HOR_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].top_l_horizontal);
<------><------><------>ret |= read_reg_otp(client, SFR_TOP_L_VER_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].top_l_vertical);
<------><------><------>ret |= read_reg_otp(client, SFR_TOP_R_HOR_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].top_r_horizontal);
<------><------><------>ret |= read_reg_otp(client, SFR_TOP_R_VER_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].top_r_vertical);
<------><------><------>ret |= read_reg_otp(client, SFR_BOTTOM_L_HOR_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].bottom_l_horizontal);
<------><------><------>ret |= read_reg_otp(client, SFR_BOTTOM_L_VER_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].bottom_l_vertical);
<------><------><------>ret |= read_reg_otp(client, SFR_BOTTOM_R_HOR_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].bottom_r_horizontal);
<------><------><------>ret |= read_reg_otp(client, SFR_BOTTOM_R_VER_REG + 16 * i,
<------><------><------><------>2, &otp_ptr->sfr_otp_data.data[i].bottom_r_vertical);
<------><------>}
<------><------>ret |= read_reg_otp(client, SFR_CHECKSUM_REG,
<------><------><------>1, &otp_ptr->sfr_otp_data.checksum);
<------><------>if (ret)
<------><------><------>goto err;
<------>}
<------>ret = read_reg_otp(client, TOTAL_CHECKSUM_REG,
<------><------>1, &otp_ptr->total_checksum);
<------>if (ret)
<------><------>goto err;
<------>if (otp_ptr->total_checksum) {
<------><------>eeprom_dev->otp = otp_ptr;
<------><------>dev_info(dev, "get otp successful\n");
<------>} else {
<------><------>eeprom_dev->otp = NULL;
<------><------>kfree(otp_ptr);
<------><------>dev_warn(&client->dev, "otp is NULL!\n");
<------>}
<------>return 0;
err:
<------>eeprom_dev->otp = NULL;
<------>kfree(otp_ptr);
<------>dev_warn(&client->dev, "@%s read otp err!\n", __func__);
<------>return -EINVAL;
}
static void rkotp_read_module_info(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;
<------>int i = 0;
<------>u32 temp = 0;
<------>u32 checksum = 0;
<------>int ret = 0;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>4, &otp_ptr->basic_data.module_size);
<------>checksum += otp_ptr->basic_data.module_size;
<------>base_addr += 4;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->basic_data.version);
<------>checksum += otp_ptr->basic_data.version;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.supplier_id);
<------>checksum += otp_ptr->basic_data.id.supplier_id;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.year);
<------>checksum += otp_ptr->basic_data.id.year;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.month);
<------>checksum += otp_ptr->basic_data.id.month;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.day);
<------>checksum += otp_ptr->basic_data.id.day;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.sensor_id);
<------>checksum += otp_ptr->basic_data.id.sensor_id;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.lens_id);
<------>checksum += otp_ptr->basic_data.id.lens_id;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.vcm_id);
<------>checksum += otp_ptr->basic_data.id.vcm_id;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.id.driver_ic_id);
<------>checksum += otp_ptr->basic_data.id.driver_ic_id;
<------>base_addr += 1;
<------>for (i = 0; i < RKMOUDLE_ID_SIZE; i++) {
<------><------>ret |= read_reg_otp(client, base_addr,
<------><------><------>1, &temp);
<------><------>otp_ptr->basic_data.modul_id[i] = temp;
<------><------>checksum += temp;
<------><------>base_addr += 1;
<------>}
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->basic_data.mirror_flip);
<------>checksum += otp_ptr->basic_data.mirror_flip;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &temp);
<------>checksum += temp;
<------>otp_ptr->basic_data.size.width = temp;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &temp);
<------>checksum += temp;
<------>otp_ptr->basic_data.size.height = temp;
<------>base_addr += 2;
<------>for (i = 0; i < RK_INFO_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->basic_data.checksum);
<------>if ((checksum % 255 + 1) == otp_ptr->basic_data.checksum && (!ret)) {
<------><------>otp_ptr->basic_data.flag = 0x01;
<------><------>otp_ptr->flag++;
<------><------>dev_info(dev, "fasic info: supplier_id(0x%x) lens(0x%x) time(%d_%d_%d) module id %x\n",
<------><------><------> otp_ptr->basic_data.id.supplier_id,
<------><------><------> otp_ptr->basic_data.id.lens_id,
<------><------><------> otp_ptr->basic_data.id.year,
<------><------><------> otp_ptr->basic_data.id.month,
<------><------><------> otp_ptr->basic_data.id.day,
<------><------><------> (u32)(*otp_ptr->basic_data.modul_id));
<------>} else {
<------><------>otp_ptr->basic_data.flag = 0;
<------><------>dev_info(dev, "fasic info: checksum err, checksum %d, reg_checksum %d\n",
<------><------><------> (int)(checksum % 255 + 1),
<------><------><------> (int)otp_ptr->basic_data.checksum);
<------><------>dev_info(dev, "fasic info: supplier_id(0x%x) lens(0x%x) time(%d_%d_%d)\n",
<------><------><------> otp_ptr->basic_data.id.supplier_id,
<------><------><------> otp_ptr->basic_data.id.lens_id,
<------><------><------> otp_ptr->basic_data.id.year,
<------><------><------> otp_ptr->basic_data.id.month,
<------><------><------> otp_ptr->basic_data.id.day);
<------><------>dev_info(dev, "fasic info: full size, width(%d) height(%d) flip(0x%x)\n",
<------><------><------> otp_ptr->basic_data.size.width,
<------><------><------> otp_ptr->basic_data.size.height,
<------><------><------> otp_ptr->basic_data.mirror_flip);
<------>}
}
static void rkotp_read_awb(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;
<------>u32 checksum = 0;
<------>u32 temp = 0;
<------>int i = 0;
<------>int ret = 0;
<------>ret = read_reg_otp(client, base_addr,
<------><------>4, &otp_ptr->awb_data.size);
<------>checksum += otp_ptr->awb_data.size;
<------>base_addr += 4;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.version);
<------>checksum += otp_ptr->awb_data.version;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.r_ratio);
<------>checksum += otp_ptr->awb_data.r_ratio;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.b_ratio);
<------>checksum += otp_ptr->awb_data.b_ratio;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.g_ratio);
<------>checksum += otp_ptr->awb_data.g_ratio;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.r_golden);
<------>checksum += otp_ptr->awb_data.r_golden;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.b_golden);
<------>checksum += otp_ptr->awb_data.b_golden;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->awb_data.g_golden);
<------>checksum += otp_ptr->awb_data.g_golden;
<------>base_addr += 2;
<------>for (i = 0; i < RK_AWB_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->awb_data.checksum);
<------>if ((checksum % 255 + 1) == otp_ptr->awb_data.checksum && (!ret)) {
<------><------>otp_ptr->awb_data.flag = 0x01;
<------><------>otp_ptr->flag++;
<------><------>dev_info(dev, "awb version:0x%x\n",
<------><------><------>otp_ptr->awb_data.version);
<------><------>dev_info(dev, "awb cur:(r 0x%x, b 0x%x, g 0x%x)\n",
<------><------><------>otp_ptr->awb_data.r_ratio,
<------><------><------>otp_ptr->awb_data.b_ratio,
<------><------><------>otp_ptr->awb_data.g_ratio);
<------><------>dev_info(dev, "awb gol:(r 0x%x, b 0x%x, g 0x%x),\n",
<------><------><------>otp_ptr->awb_data.r_golden,
<------><------><------>otp_ptr->awb_data.b_golden,
<------><------><------>otp_ptr->awb_data.g_golden);
<------>} else {
<------><------>otp_ptr->awb_data.flag = 0;
<------><------>dev_info(dev, "awb info: checksum err, checksum %d, reg_checksum %d\n",
<------><------><------>(int) (checksum % 255 + 1),
<------><------><------>(int) otp_ptr->awb_data.checksum);
<------>}
}
static void rkotp_read_lsc(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;
<------>u32 checksum = 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;
<------>base_addr += 4;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>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++) {
<------><------>otp_ptr->lsc_data.data[i] = lsc_buf[i];
<------><------>checksum += lsc_buf[i];
<------>}
<------>otp_ptr->lsc_data.table_size = LSC_DATA_SIZE;
#ifdef DEBUG
<------>w = 17 * 2;
<------>h = 17 * 4;
<------>dev_info(dev, "show lsc table\n");
<------>for (i = 0; i < h; i++) {
<------><------>for (j = 0; j < w; j++)
<------><------><------>dev_info(dev, "%d ", otp_ptr->lsc_data.data[i * w + j]);
<------><------>if (i < h)
<------><------><------>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++) {
<------><------>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)) {
<------><------>otp_ptr->lsc_data.flag = 0x01;
<------><------>otp_ptr->flag++;
<------><------>dev_info(dev, "lsc info:(version 0x%x, checksum 0x%x)\n",
<------><------><------> otp_ptr->lsc_data.version,
<------><------><------> (int)otp_ptr->lsc_data.checksum);
<------>} else {
<------><------>otp_ptr->lsc_data.flag = 0x00;
<------><------>dev_info(dev, "lsc info: checksum err, checksum %d, reg_checksum %d\n",
<------><------><------> (int)(checksum % 255 + 1),
<------><------><------> (int)otp_ptr->lsc_data.checksum);
<------>}
<------>kfree(lsc_buf);
}
static void rkotp_read_pdaf(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;
<------>u32 checksum = 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;
<------>base_addr += 4;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->pdaf_data.version);
<------>checksum += otp_ptr->pdaf_data.version;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->pdaf_data.gainmap_width);
<------>checksum += otp_ptr->pdaf_data.gainmap_width;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>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++) {
<------><------>otp_ptr->pdaf_data.gainmap[i] = pdaf_buf[i];
<------><------>checksum += otp_ptr->pdaf_data.gainmap[i];
<------>}
#ifdef DEBUG
<------>w = 64;
<------>h = 32;
<------>dev_info(dev, "show pdaf gainmap table\n");
<------>for (i = 0; i < h; i++) {
<------><------>for (j = 0; j < w; j++)
<------><------><------>dev_info(dev, "%d ", otp_ptr->pdaf_data.gainmap[i * w + j]);
<------><------>if (i < h)
<------><------><------>dev_info(dev, "\n");
<------>}
#endif
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->pdaf_data.gainmap_checksum);
<------>checksum += otp_ptr->pdaf_data.gainmap_checksum;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->pdaf_data.dcc_mode);
<------>checksum += otp_ptr->pdaf_data.dcc_mode;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->pdaf_data.dcc_dir);
<------>checksum += otp_ptr->pdaf_data.dcc_dir;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>1, &otp_ptr->pdaf_data.dccmap_width);
<------>checksum += otp_ptr->pdaf_data.dccmap_width;
<------>base_addr += 1;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>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++) {
<------><------>otp_ptr->pdaf_data.dccmap[i] = pdaf_buf[i];
<------><------>checksum += otp_ptr->pdaf_data.dccmap[i];
<------>}
<------>base_addr += RK_DCCMAP_SIZE;
#ifdef DEBUG
<------>w = 32;
<------>h = 16;
<------>dev_info(dev, "show pdaf dccmap table\n");
<------>for (i = 0; i < h; i++) {
<------><------>for (j = 0; j < w; j++)
<------><------><------>dev_info(dev, "%d ", otp_ptr->pdaf_data.dccmap[i * w + j]);
<------><------>if (i < h)
<------><------><------>dev_info(dev, "\n");
<------>}
#endif
<------>ret |= read_reg_otp(client, base_addr,
<------><------>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++) {
<------><------>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)) {
<------><------>otp_ptr->pdaf_data.flag = 0x01;
<------><------>otp_ptr->flag++;
<------><------>dev_info(dev, "pdaf info:(version 0x%x, checksum 0x%x)\n",
<------><------><------> otp_ptr->pdaf_data.version,
<------><------><------> (int)otp_ptr->pdaf_data.checksum);
<------>} else {
<------><------>otp_ptr->pdaf_data.flag = 0x00;
<------><------>dev_info(dev, "pdaf info: checksum err, checksum %d, reg_checksum %d\n",
<------><------><------> (int)(checksum % 255 + 1),
<------><------><------> (int)otp_ptr->pdaf_data.checksum);
<------>}
<------>kfree(pdaf_buf);
}
static void rkotp_read_af(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;
<------>u32 checksum = 0;
<------>u32 temp = 0;
<------>int i = 0;
<------>int ret = 0;
<------>ret = read_reg_otp(client, base_addr,
<------><------>4, &otp_ptr->af_data.size);
<------>checksum += otp_ptr->af_data.size;
<------>base_addr += 4;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->af_data.version);
<------>checksum += otp_ptr->af_data.version;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->af_data.af_inf);
<------>checksum += otp_ptr->af_data.af_inf;
<------>base_addr += 2;
<------>ret |= read_reg_otp(client, base_addr,
<------><------>2, &otp_ptr->af_data.af_macro);
<------>checksum += otp_ptr->af_data.af_macro;
<------>base_addr += 2;
<------>for (i = 0; i < RK_AF_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->af_data.checksum);
<------>if ((checksum % 255 + 1) == otp_ptr->af_data.checksum && (!ret)) {
<------><------>otp_ptr->af_data.flag = 0x01;
<------><------>otp_ptr->flag++;
<------><------>dev_info(dev, "af info:(version 0x%x, checksum 0x%x)\n",
<------><------><------> otp_ptr->af_data.version,
<------><------><------> (int)otp_ptr->af_data.checksum);
<------>} else {
<------><------>otp_ptr->af_data.flag = 0x00;
<------><------>dev_info(dev, "af info: checksum err, checksum %d, reg_checksum %d\n",
<------><------><------> (int)(checksum % 255 + 1),
<------><------><------> (int)otp_ptr->af_data.checksum);
<------>}
}
static int rkotp_read_data(struct eeprom_device *eeprom_dev)
{
<------>struct i2c_client *client = eeprom_dev->client;
<------>struct otp_info *otp_ptr;
<------>struct device *dev = &eeprom_dev->client->dev;
<------>u32 id = 0;
<------>u32 base_addr = 0;
<------>int i = 0;
<------>int ret = 0;
<------>otp_ptr = kzalloc(sizeof(*otp_ptr), GFP_KERNEL);
<------>if (!otp_ptr)
<------><------>return -ENOMEM;
<------>base_addr = RKOTP_REG_START;
<------>otp_ptr->flag = 0;
<------>for (i = 0; i < RKOTP_MAX_MODULE; i++) {
<------><------>read_reg_otp(client, base_addr, 1, &id);
<------><------>dev_info(dev, "show block id %d, addr 0x%x\n", id, base_addr);
<------><------>switch (id) {
<------><------>case RKOTP_INFO_ID:
<------><------><------>rkotp_read_module_info(eeprom_dev,
<------><------><------><------>otp_ptr,
<------><------><------><------>base_addr + 1);
<------><------><------>base_addr += 0x28;//v1 0x30 v2 0x28;
<------><------><------>break;
<------><------>case RKOTP_AWB_ID:
<------><------><------>rkotp_read_awb(eeprom_dev,
<------><------><------><------>otp_ptr,
<------><------><------><------>base_addr + 1);
<------><------><------>base_addr += 0x30;
<------><------><------>break;
<------><------>case RKOTP_LSC_ID:
<------><------><------>rkotp_read_lsc(eeprom_dev,
<------><------><------><------>otp_ptr,
<------><------><------><------>base_addr + 1);
<------><------><------>base_addr += 0x930;
<------><------><------>break;
<------><------>case RKOTP_PDAF_ID:
<------><------><------>rkotp_read_pdaf(eeprom_dev,
<------><------><------><------>otp_ptr,
<------><------><------><------>base_addr + 1);
<------><------><------>base_addr += 0xA30;
<------><------><------>break;
<------><------>case RKOTP_AF_ID:
<------><------><------>rkotp_read_af(eeprom_dev,
<------><------><------><------>otp_ptr,
<------><------><------><------>base_addr + 1);
<------><------><------>base_addr += 0x20;
<------><------><------>break;
<------><------>default:
<------><------><------>id = -1;
<------><------><------>break;
<------><------>}
<------><------>if (id == -1)
<------><------><------>break;
<------>}
<------>if (otp_ptr->flag) {
<------><------>eeprom_dev->otp = otp_ptr;
<------><------>dev_info(dev, "rkotp read successful!\n");
<------>} else {
<------><------>eeprom_dev->otp = NULL;
<------><------>kfree(otp_ptr);
<------><------>dev_warn(&client->dev, "otp is NULL!\n");
<------><------>ret = -1;
<------>}
<------>return ret;
}
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);
<------>else if (vendor_flag == 0x40)
<------><------>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;
}
static long eeprom_ioctl(struct v4l2_subdev *sd,
<------>unsigned int cmd, void *arg)
{
<------>struct eeprom_device *eeprom_dev =
<------><------>sd_to_eeprom(sd);
<------>long ret = 0;
<------>if (!eeprom_dev->otp) {
<------><------>if (otp_read(eeprom_dev))
<------><------><------>ret = -EFAULT;
<------>}
<------>if (arg && eeprom_dev->otp)
<------><------>memcpy(arg, eeprom_dev->otp,
<------><------><------>sizeof(struct otp_info));
<------>else
<------><------>ret = -EFAULT;
<------>return ret;
}
#ifdef CONFIG_PROC_FS
static int otp_eeprom_show(struct seq_file *p, void *v)
{
<------>struct eeprom_device *dev = p->private;
<------>int i = 0;
<------>int j = 0;
<------>u32 gainmap_w, gainmap_h;
<------>u32 dccmap_w, dccmap_h;
<------>if (dev && dev->otp) {
<------><------>seq_puts(p, "[Header]\n");
<------><------>seq_puts(p, "version=1.0;\n\n");
<------><------>if (dev->otp->awb_data.flag) {
<------><------><------>seq_puts(p, "[RKAWBOTPParam]\n");
<------><------><------>seq_printf(p, "flag=%d;\n", dev->otp->awb_data.flag);
<------><------><------>seq_printf(p, "r_value=%d;\n", dev->otp->awb_data.r_ratio);
<------><------><------>seq_printf(p, "b_value=%d;\n", dev->otp->awb_data.b_ratio);
<------><------><------>seq_printf(p, "gr_value=%d;\n", dev->otp->awb_data.g_ratio);
<------><------><------>seq_puts(p, "gb_value=-1;\n");
<------><------><------>seq_printf(p, "golden_r_value=%d;\n", dev->otp->awb_data.r_golden);
<------><------><------>seq_printf(p, "golden_b_value=%d;\n", dev->otp->awb_data.b_golden);
<------><------><------>seq_printf(p, "golden_gr_value=%d;\n", dev->otp->awb_data.g_golden);
<------><------><------>seq_puts(p, "golden_gb_value=-1;\n\n");
<------><------><------>seq_puts(p, "[RKLSCOTPParam]\n");
<------><------><------>seq_printf(p, "flag=%d;\n", dev->otp->lsc_data.flag);
<------><------><------>seq_printf(p, "width=%d;\n", dev->otp->basic_data.size.width);
<------><------><------>seq_printf(p, "height=%d;\n", dev->otp->basic_data.size.height);
<------><------><------>seq_printf(p, "tablesize=%d;\n\n", dev->otp->lsc_data.table_size);
<------><------><------>seq_puts(p, "lsc_r_table=\n");
<------><------><------>for (i = 0; i < 17; i++) {
<------><------><------><------>for (j = 0; j < 17; j++) {
<------><------><------><------><------>seq_printf(p, "%d", (dev->otp->lsc_data.data[(i * 17 + j) * 2] << 8)
<------><------><------><------><------><------>| dev->otp->lsc_data.data[(i * 17 + j) * 2 + 1]);
<------><------><------><------><------>if (j < 16)
<------><------><------><------><------><------>seq_puts(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < 16)
<------><------><------><------><------>seq_puts(p, "\n");
<------><------><------>}
<------><------><------>seq_puts(p, "\n\n");
<------><------>}
<------><------>if (dev->otp->lsc_data.flag) {
<------><------><------>seq_puts(p, "lsc_b_table=\n");
<------><------><------>for (i = 0; i < 17; i++) {
<------><------><------><------>for (j = 0; j < 17; j++) {
<------><------><------><------><------>seq_printf(p, "%d", (dev->otp->lsc_data.data[(i * 17 + j) * 2 +
<------><------><------><------><------><------>1734] << 8) | dev->otp->lsc_data.data[(i * 17 + j) *
<------><------><------><------><------><------>2 + 1735]);
<------><------><------><------><------>if (j < 16)
<------><------><------><------><------><------>seq_puts(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < 16)
<------><------><------><------><------>seq_puts(p, "\n");
<------><------><------>}
<------><------><------>seq_puts(p, "\n\n");
<------><------><------>seq_puts(p, "lsc_gr_table=\n");
<------><------><------>for (i = 0; i < 17; i++) {
<------><------><------><------>for (j = 0; j < 17; j++) {
<------><------><------><------><------>seq_printf(p, "%d", (dev->otp->lsc_data.data[(i * 17 + j) * 2 +
<------><------><------><------><------><------>578] << 8) | dev->otp->lsc_data.data[(i * 17 + j) *
<------><------><------><------><------><------>2 + 579]);
<------><------><------><------><------>if (j < 16)
<------><------><------><------><------><------>seq_puts(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < 16)
<------><------><------><------><------>seq_puts(p, "\n");
<------><------><------>}
<------><------><------>seq_puts(p, "\n\n");
<------><------><------>seq_puts(p, "lsc_gb_table=\n");
<------><------><------>for (i = 0; i < 17; i++) {
<------><------><------><------>for (j = 0; j < 17; j++) {
<------><------><------><------><------>seq_printf(p, "%d", (dev->otp->lsc_data.data[(i * 17 + j) * 2 +
<------><------><------><------><------><------>1156] << 8) | dev->otp->lsc_data.data[(i * 17 + j) *
<------><------><------><------><------><------>2 + 1157]);
<------><------><------><------><------>if (j < 16)
<------><------><------><------><------><------>seq_puts(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < 16)
<------><------><------><------><------>seq_puts(p, "\n");
<------><------><------>}
<------><------><------>seq_puts(p, "\n\n");
<------><------>}
<------><------>if (dev->otp->pdaf_data.flag) {
<------><------><------>gainmap_w = dev->otp->pdaf_data.gainmap_width;
<------><------><------>gainmap_h = dev->otp->pdaf_data.gainmap_height;
<------><------><------>dccmap_w = dev->otp->pdaf_data.dccmap_width;
<------><------><------>dccmap_h = dev->otp->pdaf_data.dccmap_height;
<------><------><------>seq_printf(p, "[RKPDAFOTPParam]\n");
<------><------><------>seq_printf(p, "flag=%d;\n", dev->otp->pdaf_data.flag);
<------><------><------>seq_printf(p, "gainmap_width=%d;\n", gainmap_w);
<------><------><------>seq_printf(p, "gainmap_height=%d;\n", gainmap_h);
<------><------><------>seq_printf(p, "gainmap_table=\n");
<------><------><------>for (i = 0; i < gainmap_h; i++) {
<------><------><------><------>for (j = 0; j < gainmap_w; j++) {
<------><------><------><------><------>seq_printf(p, "%d",
<------><------><------><------><------><------> (dev->otp->pdaf_data.gainmap[(i * gainmap_w + j) * 2] << 8) |
<------><------><------><------><------><------> dev->otp->pdaf_data.gainmap[(i * gainmap_w + j) * 2 + 1]);
<------><------><------><------><------>if (j < gainmap_w)
<------><------><------><------><------><------>seq_printf(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < gainmap_h)
<------><------><------><------><------>seq_printf(p, "\n");
<------><------><------>}
<------><------><------>seq_printf(p, "\n");
<------><------><------>seq_printf(p, "dcc_mode=%d\n", dev->otp->pdaf_data.dcc_mode);
<------><------><------>seq_printf(p, "dcc_dir=%d\n", dev->otp->pdaf_data.dcc_dir);
<------><------><------>seq_printf(p, "dccmap_width=%d\n", dev->otp->pdaf_data.dccmap_width);
<------><------><------>seq_printf(p, "dccmap_height=%d\n", dev->otp->pdaf_data.dccmap_height);
<------><------><------>for (i = 0; i < dccmap_h; i++) {
<------><------><------><------>for (j = 0; j < dccmap_w; j++) {
<------><------><------><------><------>seq_printf(p, "%d",
<------><------><------><------><------><------> (dev->otp->pdaf_data.dccmap[(i * dccmap_w + j) * 2] << 8) |
<------><------><------><------><------><------> dev->otp->pdaf_data.dccmap[(i * dccmap_w + j) * 2 + 1]);
<------><------><------><------><------>if (j < dccmap_w)
<------><------><------><------><------><------>seq_printf(p, " ");
<------><------><------><------>}
<------><------><------><------>if (i < dccmap_h)
<------><------><------><------><------>seq_printf(p, "\n");
<------><------><------>}
<------><------><------>seq_printf(p, "\n");
<------><------>}
<------><------>if (dev->otp->af_data.flag) {
<------><------><------>seq_printf(p, "[RKAFOTPParam]\n");
<------><------><------>seq_printf(p, "flag=%d;\n", dev->otp->af_data.flag);
<------><------><------>seq_printf(p, "af_inf=%d;\n", dev->otp->af_data.af_inf);
<------><------><------>seq_printf(p, "af_macro=%d;\n", dev->otp->af_data.af_macro);
<------><------>}
<------>} else {
<------><------>seq_puts(p, "otp is null!\n");
<------>}
<------>return 0;
}
static int eeprom_open(struct inode *inode, struct file *file)
{
<------>struct eeprom_device *data = PDE_DATA(inode);
<------>return single_open(file, otp_eeprom_show, data);
}
static const struct proc_ops ops = {
<------>.proc_open = eeprom_open,
<------>.proc_read = seq_read,
<------>.proc_lseek = seq_lseek,
<------>.proc_release = single_release,
};
static int eeprom_proc_init(struct eeprom_device *dev)
{
<------>dev->procfs = proc_create_data(dev->name, 0, NULL, &ops, dev);
<------>if (!dev->procfs)
<------><------>return -EINVAL;
<------>return 0;
}
static void eeprom_proc_cleanup(struct eeprom_device *dev)
{
<------>if (dev->procfs)
<------><------>remove_proc_entry(dev->name, NULL);
<------>dev->procfs = NULL;
}
#endif
static const struct v4l2_subdev_core_ops eeprom_core_ops = {
<------>.ioctl = eeprom_ioctl,
};
static const struct v4l2_subdev_ops eeprom_ops = {
<------>.core = &eeprom_core_ops,
};
static void eeprom_subdev_cleanup(struct eeprom_device *dev)
{
<------>v4l2_device_unregister_subdev(&dev->sd);
<------>media_entity_cleanup(&dev->sd.entity);
}
static int eeprom_probe(struct i2c_client *client,
<------>const struct i2c_device_id *id)
{
<------>struct eeprom_device *eeprom_dev;
<------>dev_info(&client->dev, "driver version: %02x.%02x.%02x",
<------><------> DRIVER_VERSION >> 16,
<------><------> (DRIVER_VERSION & 0xff00) >> 8,
<------><------> DRIVER_VERSION & 0x00ff);
<------>eeprom_dev = devm_kzalloc(&client->dev,
<------><------>sizeof(*eeprom_dev),
<------><------>GFP_KERNEL);
<------>if (eeprom_dev == NULL) {
<------><------>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;
<------>snprintf(eeprom_dev->name, sizeof(eeprom_dev->name), "%s-%d-%02x",
<------><------> DEVICE_NAME, i2c_adapter_id(client->adapter), client->addr);
<------>eeprom_proc_init(eeprom_dev);
<------>pm_runtime_set_active(&client->dev);
<------>pm_runtime_enable(&client->dev);
<------>pm_runtime_idle(&client->dev);
<------>dev_info(&client->dev, "probing successful\n");
<------>return 0;
}
static int eeprom_remove(struct i2c_client *client)
{
<------>struct v4l2_subdev *sd = i2c_get_clientdata(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);
<------>return 0;
}
static int __maybe_unused eeprom_suspend(struct device *dev)
{
<------>return 0;
}
static int __maybe_unused eeprom_resume(struct device *dev)
{
<------>return 0;
}
static const struct i2c_device_id eeprom_id_table[] = {
<------>{ DEVICE_NAME, 0 },
<------>{ { 0 } }
};
MODULE_DEVICE_TABLE(i2c, eeprom_id_table);
static const struct of_device_id eeprom_of_table[] = {
<------>{ .compatible = "rk,otp_eeprom" },
<------>{ { 0 } }
};
MODULE_DEVICE_TABLE(of, eeprom_of_table);
static const struct dev_pm_ops eeprom_pm_ops = {
<------>SET_SYSTEM_SLEEP_PM_OPS(eeprom_suspend, eeprom_resume)
<------>SET_RUNTIME_PM_OPS(eeprom_suspend, eeprom_resume, NULL)
};
static struct i2c_driver eeprom_i2c_driver = {
<------>.driver = {
<------><------>.name = DEVICE_NAME,
<------><------>.pm = &eeprom_pm_ops,
<------><------>.of_match_table = eeprom_of_table,
<------>},
<------>.probe = &eeprom_probe,
<------>.remove = &eeprom_remove,
<------>.id_table = eeprom_id_table,
};
module_i2c_driver(eeprom_i2c_driver);
MODULE_DESCRIPTION("OTP driver");
MODULE_LICENSE("GPL v2");