【Camera专题】OTP数据如何保存在自定义节点中

一、前言

之前因为lsc导致出现的绿屏问题,模组厂说是lsc数据出了异常,
sensor厂fae也没有后续配合,就扯了一句,让我们保存otp数据,
方便出问题时对比,然后就没有然后了。支持不给力,态度还差。

若对OTP不太熟悉,先读一下以前的文章!
OTP编程完全指南分上、下2篇。
上:主要讲OTP的知识和调试流程。
下:主要讲OTP的源码。

Qcom-高通OTP编程调试指南-上
Qcom-高通OTP编程调试指南-下

二、知识点

其实呢,这些数据在kernel层是有打印出来的,如图:

但是系统组的人说这些log太多了,影响kernel的启动,要我们保存在节点中,通过cat命令去获得。

2.1 总体思路

  • 1.创建节点
  • 2.实现read函数(使用cat命令时会主动调read函数)

2.2 具体实现
kernel/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c

#include <linux/debugfs.h>  //需要的头文件
#define OTP_SZIE_S5K4H7 400  //otp数据大小
static uint8_t otp_lsc_temp[OTP_SZIE_S5K4H7];//数组,用于保存数据
char otp_lsc_buffer[1024];//数组,用于保存数据

#define OTP_LSC_DATA "data"
#define OTP_LSC_PATH "/sys/kernel/debug/otp/lsc_data" //节点路径

//读函数
ssize_t read_otp_lsc(struct file *filp, char __user *userbuf,
                                                              size_t count, loff_t *ppos)
{
      int i;
      int j = 1;
      char temp[OTP_SZIE_S5K4H7] = {0};
    CDBG("zcf read_otp_lsc enter\n");
      memset(otp_lsc_buffer, 0, sizeof(otp_lsc_buffer));
      strlcat(otp_lsc_buffer, "AWB:\n", sizeof(otp_lsc_buffer));//AWB数据
      for (i = 0; i < OTP_SZIE_S5K4H7; i++) {
              snprintf(temp, sizeof(temp), "%02x", otp_lsc_temp[i]);
              strlcat(otp_lsc_buffer, temp, sizeof(otp_lsc_buffer));
              strlcat(otp_lsc_buffer, " ", sizeof(otp_lsc_buffer));   
              if(i == 59)//前60个是AWB数据
                      strlcat(otp_lsc_buffer, "\nLSC:\n", sizeof(otp_lsc_buffer));
              if(i == 10*j-1)//每打印10个数字就换行
              {
                      j++;
                      strlcat(otp_lsc_buffer, "\r\n", sizeof(otp_lsc_buffer));
              }
      }
      strlcat(otp_lsc_buffer, "\r\n", sizeof(otp_lsc_buffer));//换行
      return simple_read_from_buffer(userbuf, count,
        ppos, otp_lsc_buffer, strlen(otp_lsc_buffer));
}

static const struct file_operations otp_lsc_fops = {
              .read = read_otp_lsc,//赋值读函数
};

//创建节点 /sys/kernel/debug/otp/lsc_data
static int otp_init_debugfs(void)
{
      int ret = 0;
      struct dentry *root;
      root = debugfs_create_dir("otp", NULL);
      if(!root)
      {
          CDBG("zcf %s debugfs_create_dir(otp) failed\n", __func__);  
              ret = -ENOMEM;
              return ret;
      }
      if (!debugfs_create_file(OTP_LSC_DATA,
                              0666,
                              root,
                              NULL,
                              &otp_lsc_fops));
      {
              CDBG("zcf %s failed to create lsc_data debugfs file\n", __func__);      
              ret = -ENOMEM;
              return ret;
      }

      return ret;
}

调用的地方

static int msm_eeprom_i2c_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
{
···省略部分代码
      //在probe中创建节点
++      otp_init_debugfs(); 
···省略部分代码
         rc = read_eeprom_memory(e_ctrl, &e_ctrl->cal_data);//这里会读取数据

++       if(0 == strcmp(eb_info->eeprom_name,"sunwin_s5k4h7")){
++           pr_err("zcf [sensor: s5k4h7]save the otp data\n");
++           for (j = 0; j < e_ctrl->cal_data.num_data; j++)
                    //把读出来的数据保存在临时数组otp_lsc_temp中
++               otp_lsc_temp[j] = e_ctrl->cal_data.mapdata[j];
++       }

···省略部分代码
}

结果

在这里插入图片描述

三、创建一个camera 节点,保存sensor名称

kernel/msm-4.9/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c

/*
* 创建节点
* 1.  /sys/kernel/debug/bbk_camera/back_cam_name
* 2.  /sys/kernel/debug/bbk_camera/front_cam_name
*/
char front_name_buffer[32]="NULL";//前摄名称
char back_name_buffer[32]="NULL";//后摄名称
ssize_t read_front_name(struct file *filp, char __user *userbuf,
                        size_t count, loff_t *ppos)
{
    char kbuf[32]="NULL";
    sprintf(kbuf, "%s\n", front_name_buffer);
    return simple_read_from_buffer(userbuf, count,ppos, kbuf, strlen(kbuf));
}
ssize_t read_back_name(struct file *filp, char __user *userbuf,
                        size_t count, loff_t *ppos)
{
    char kbuf[32]="NULL";
    sprintf(kbuf, "%s\n", back_name_buffer);
    return simple_read_from_buffer(userbuf, count,ppos, kbuf, strlen(kbuf));
}
static const struct file_operations front_camera_fops = {
    .read = read_front_name,//赋值读函数
};
static const struct file_operations back_camera_fops = {
    .read = read_back_name,//赋值读函数
};
static int camera_node_create(void)
{
    int ret = 0; 
    struct dentry *root;
    root = debugfs_create_dir("bbk_camera", NULL);
    if(!root)
    {    
        CDBG("zcf %s debugfs_create_dir(bbk_camera) failed\n", __func__);
        ret = -ENOMEM;
        return ret;
    }
    if(root){
        debugfs_create_file("front_cam_name",
                            0666,
                            root,
                            NULL,
                            &front_camera_fops);
        debugfs_create_file("back_cam_name",
                            0666,
                            root,
                            NULL,
                            &back_camera_fops);
    }
    return ret;
}

int32_t msm_sensor_driver_probe(void *setting,
    struct msm_sensor_info_t *probed_info, char *entity_name)
{
  ···
    camera_node_create();

    pr_err("%s probe succeeded", slave_info->sensor_name);
    ···

    if(slave_info->sensor_init_params.position == 1) {
        strlcpy(front_name_buffer, slave_info->sensor_name,
                sizeof(front_name_buffer));
        CDBG("front_name_buffer= %s\n",front_name_buffer);
    }else {
        strlcpy(back_name_buffer, slave_info->sensor_name,
                sizeof(back_name_buffer));
        CDBG("back_name_buffer= %s\n",back_name_buffer);
    }
  ···
}

结果

Stay Hungry,Stay Foolish!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值