<8974_LUS7321>
拟制: Prepared by 邱绪东日期:
Date
2013-07-08
审核: Reviewed by 日期:
Date
yyyy-mm-dd
审核: Reviewed by 日期:
Date
yyyy-mm-dd
批准: Granted by
日期:
Date
yyyy-mm-dd
青岛海信移动技术股份有限公司
版权所有侵权必究
修订记录Revision record
目录
软件模块设计方案 (1)
1 引言 (1)
1.1 编写目的 (1)
1.2 术语表 (1)
1.3 参考资料 (1)
2 模块总体方案设计 (1)
2.1 技术简介 (1)
2.2 硬件架构 (2)
2.3 软件结构 (2)
2.4 流程分析 (3)
3 Driver Code Porting Changes (8)
3.1 宏定义.......................................................................................... 错误!未定义书签。
3.2 数据结构定义.............................................................................. 错误!未定义书签。
3.3 全局变量...................................................................................... 错误!未定义书签。
3.4 接口函数...................................................................................... 错误!未定义书签。
3.5 信号、命令和事件列表.............................................................. 错误!未定义书签。
软件模块设计方案
1 引言
1.1 编写目的
本设计文档目的是为高通平台8974平台camera模块设计人员和开发人员提供指导,为软件的详细设计奠定基础。
1.2 术语表
HAL:Hardware application layer
CPP:Camera Postprocessor
1.3 参考资料
1、80-NA157-22_A_MSM8974_Linux_Camera_Overview
2、80-NA157-17_B_MSM8974_Multimedia_Overview
3、80-NF071-1_A_Sensor_Arch_Code_Walkthrough_Camera20_Linux_Camera_SW
4、80-NE717-1_C_MSM8974_APQ8074_MSM8x26_Linux_Camera_SDD
2 模块总体方案设计
2.1 技术简介
2.1.1 硬件变化:
(1)8974 VFE 版本从3.2升级到4.0,并且增加了一个VFE处理,其中,一个最大
21Mpixel/s, 还有一个13.5Mpixel/s;VFE4 普通模式下最大266MHz , Turbo 模式下最大320MHz。
(2)8974 增加一个JPEG硬编码处理,编码器普通模式下最大时钟266MHz,Turbo 模式下最大320MHz。
(3)增加了CPP模块(Camera Postprocessor),该模块的作用是:支持flip/rotate, denoise,smooth/sharpen,crop,upscale features full-size VFE output frames.
(4)硬件解码器的速度从50MPps提高到166MPps。
2.1.2 MSM8974 VS MSM8960区别:
2.2 硬件架构
2.3 软件结构
2.4 流程分析
1、Camera 模块流程:
2、Module probe 流程图:
3、MCT model init 时序图
4、sensor architecture
Video node (/dev/videoX): One video node for every successful sensor probe (back, front camera)
V4l2 subdev (/dev/v4l-subdevX): CSIPHY0, CSID0,Actuator0, EEPROM0,LED flash0,Strobe flash0.
Kernel space细分:
Userspace细分:
5、状态图
Camera HAL State Machine
Channel 状态机
Stream 状态机
3 Driver Code Porting Changes
3.1 Kernel space driver changes
(1)Add DTSI and DTS FILE
添加dtsi文件
DTS实际上是一种数据结构,用来描述硬件设备(资源)。
Add sensors : msm8974-camera-sensor-mtp.dtsi,配置了sensor的属性和资源。
Add subdevs: msm8974_camera.dtsi,配置了sensor的属性和资源。
(2)DTSI and probe
添加XXX_sensor.c
使用Device Tree后,驱动需要与.dts中描述的设备结点进行匹配,从而引发驱动的probe()函数执行。对于sensor driver而言,需要添加一个OF匹配表。
static const struct of_device_id s5k3l1yx_dt_match[] = {
{.compatible = "qcom,s5k3l1yx", .data = &s5k3l1yx_s_ctrl},
{}
};
MODULE_DEVICE_TABLE(of, s5k3l1yx_dt_match);
static struct platform_driver s5k3l1yx_platform_driver = {
.driver = {
.name = "qcom,s5k3l1yx",
.owner = THIS_MODULE,
.of_match_table = s5k3l1yx_dt_match,
},
};
static int __init s5k3l1yx_init_module(void)
{
int32_t rc = 0;
pr_info("%s:%d\n", __func__, __LINE__);
rc = platform_driver_probe(&s5k3l1yx_platform_driver,
s5k3l1yx_platform_probe); //挂载probe函数
if (!rc)
return rc;
pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
return i2c_add_driver(&s5k3l1yx_i2c_driver); //执行probe函数
}
static int32_t s5k3l1yx_platform_probe(struct platform_device *pdev)
{
int32_t rc = 0;
const struct of_device_id *match;
match = of_match_device(s5k3l1yx_dt_match, &pdev->dev);
rc = msm_sensor_platform_probe(pdev, match->data);
return rc;
}
(3)Init and exit process
Init()
Add platform driver
Execute power up sequence
Read chip ID; if chip ID matches, create a video node (/dev/VideoX)
Execute power down sequence
Exit()
Remove platform driver
Power sequence specific to every sensor
3.2 User Space Driver Changes
(1)sensor寄存器组织方式
之前XXX.c中寄存器组等信息,拆分到USERSPACE XXX _lib.c 文件
例如:
android\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\mo dules\sensors\sensor_libs\s5k3l1yx\ s5k3l1yx_lib.c
在应用层sensor.c中会调用寄存器组
\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\se nsors\sensors\sensor.c
static int32_t sensor_get_res_cfg_table(void *sctrl, void *data)
{
sensor_ctrl_t *ctrl = (sensor_ctrl_t *)sctrl;
struct sensor_res_cfg_table_t **res_cfg =
(struct sensor_res_cfg_table_t **)data;
if (!res_cfg) {
SERR("failed");
return SENSOR_FAILURE;
}
*res_cfg = ctrl->lib_params->sensor_lib_ptr->sensor_res_cfg_table;
return SENSOR_SUCCESS;
}
(2)寄存器设置流程
Z:\work1\code\8974_postCS\8974_postCS_android\vendor\qcom\proprietary\mm-camera\ mm-camera2\media-controller\modules\sensors\module\ module_sensor.c
static boolean module_sensor_event_control_set_parm( //应用层的config接口mct_module_t *module, mct_event_t* event,
module_sensor_bundle_info_t *s_bundle)
\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\sensor s\sensor.c
调入sensor.c //集成所有函数接口
/*==========================================================
* FUNCTION - sensor_process -
*
* DESCRIPTION:
*==========================================================*/ static int32_t sensor_process(void *sctrl,
sensor_submodule_event_type_t event, void *data)
{
int32_t rc = SENSOR_SUCCESS;
if (!sctrl) {
SERR("failed");
return SENSOR_FAILURE;
}
SLOW("sctrl %p event %d", sctrl, event);
switch (event) {
/* Get enums */
case SENSOR_GET_CAPABILITIES:
rc = sensor_get_capabilities(sctrl, data);
break;
case SENSOR_GET_CUR_CSIPHY_CFG:
rc = sensor_get_cur_csiphy_cfg(sctrl, data);
break;
case SENSOR_GET_CUR_CSID_CFG:
rc = sensor_get_cur_csid_cfg(sctrl, data);
break;
case SENSOR_GET_CUR_CHROMA TIX_NAME:
rc = sensor_get_cur_chromatix_name(sctrl, data);
break;
case SENSOR_GET_CSI_LANE_PARAMS:
rc = sensor_get_csi_lane_params(sctrl, data);
break;
case SENSOR_GET_CUR_FPS:
rc = sensor_get_cur_fps(sctrl, data);
break;
case SENSOR_GET_RESOLUTION_INFO:
rc = sensor_get_resolution_info(sctrl, data);
break;
case SENSOR_GET_RES_CFG_TABLE:
rc = sensor_get_res_cfg_table(sctrl, data);
break;
case SENSOR_GET_SENSOR_PORT_INFO:
rc = sensor_get_sensor_port_info(sctrl, data);
break;
case SENSOR_GET_DIGITAL_GAIN:
rc = sensor_get_digital_gain(sctrl, data); break;
case SENSOR_GET_SENSOR_FORMA T:
rc = sensor_get_sensor_format(sctrl, data); break;
/* Set enums */
case SENSOR_SET_LIB_PARAMS:
rc = sensor_set_lib_params(sctrl, data); break;
case SENSOR_SET_INIT_PARAMS:
rc = sensor_set_init_params(sctrl, data); break;
case SENSOR_SET_SUBDEV_INFO:
rc = sensor_set_subdev_info(sctrl, data); break;
case SENSOR_INIT:
rc = sensor_init(sctrl);
break;
case SENSOR_STOP_STREAM:
rc = sensor_set_stop_stream(sctrl); break;
case SENSOR_START_STREAM:
rc = sensor_set_start_stream(sctrl); break;
case SENSOR_SET_RESOLUTION:
rc = sensor_set_resolution(sctrl, data); break;
case SENSOR_SET_AEC_UPDATE:
rc = sensor_set_aec_update(sctrl, data); break;
case SENSOR_SET_AEC_INIT_SETTINGS: rc = sensor_set_aec_init_settings(sctrl, data); break;
case SENSOR_SET_VFE_SOF:
rc = sensor_set_vfe_sof(sctrl);
break;
case SENSOR_SET_FPS:
rc = sensor_set_frame_rate(sctrl, data); break;
case SENSOR_SET_HFR_MODE:
rc = sensor_set_hfr_mode(sctrl, data); break;
case SENSOR_GET_W AIT_FRAMES:
rc = sensor_get_wait_frames(sctrl, data);
break;
case SENSOR_SET_WAIT_FRAMES:
rc = sensor_set_wait_frames(sctrl, data);
break;
case SENSOR_SET_HDR_AE_BRACKET:
rc = sensor_set_hdr_ae_bracket(sctrl, data);
break;
case SENSOR_SET_DIS_ENABLE:
rc = sensor_set_dis_enable(sctrl, data);
break;
default:
SERR("invalid event %d", event);
rc = SENSOR_FAILURE;
break;
}
return rc;
}
/*======================================================== * FUNCTION - sensor_set_start_stream -
*
* DESCRIPTION:
*=======================================================*/ static int8_t sensor_set_start_stream(void *sctrl)
{
struct sensorb_cfg_data cfg;
sensor_ctrl_t *ctrl = (sensor_ctrl_t *)sctrl;
sensor_lib_params_t *lib = (sensor_lib_params_t *)ctrl->lib_params;
SLOW("enter");
if (ctrl->s_data->fd < 0)
return FALSE;
if (lib->sensor_lib_ptr->sensor_output->output_format != SENSOR_YCBCR) { cfg.cfgtype = CFG_WRITE_I2C_ARRAY;
cfg.cfg.setting = ctrl->lib_params->sensor_lib_ptr->start_settings;
} else {
cfg.cfgtype = CFG_SET_START_STREAM;
}
if (ioctl(ctrl->s_data->fd, VIDIOC_MSM_SENSOR_CFG, &cfg) < 0) {
SLOW("failed");
return 0;
}
SLOW("exit");
return TRUE;
}
Msm_sensor.c
static long msm_sensor_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
void __user *argp = (void __user *)arg;
if (!s_ctrl) {
pr_err("%s s_ctrl NULL\n", __func__);
return -EBADF;
}
switch (cmd) {
case VIDIOC_MSM_SENSOR_CFG:
return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
case MSM_SD_SHUTDOWN:
msm_sensor_stop_stream(s_ctrl);
return 0;
default:
return -ENOIOCTLCMD;
}
}
S5k3l1yx.c
.sensor_config = msm_sensor_config,
int32_t msm_sensor_config(struct msm_sensor_ctrl_t *s_ctrl, void __user *argp)
{
struct sensorb_cfg_data *cdata = (struct sensorb_cfg_data *)argp;
long rc = 0;
int32_t i = 0;
mutex_lock(s_ctrl->msm_sensor_mutex);
CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__, s_ctrl->sensordata->sensor_name, cdata->cfgtype);
switch (cdata->cfgtype) {
case CFG_GET_SENSOR_INFO:
memcpy(cdata->cfg.sensor_info.sensor_name,
s_ctrl->sensordata->sensor_name,
sizeof(cdata->cfg.sensor_info.sensor_name));
cdata->cfg.sensor_info.session_id =
s_ctrl->sensordata->sensor_info->session_id;
for (i = 0; i < SUB_MODULE_MAX; i++)
cdata->cfg.sensor_info.subdev_id[i] =
s_ctrl->sensordata->sensor_info->subdev_id[i];
CDBG("%s:%d sensor name %s\n", __func__, __LINE__,
cdata->cfg.sensor_info.sensor_name);
CDBG("%s:%d session id %d\n", __func__, __LINE__,
cdata->cfg.sensor_info.session_id);
for (i = 0; i < SUB_MODULE_MAX; i++)
CDBG("%s:%d subdev_id[%d] %d\n", __func__, __LINE__, i,
cdata->cfg.sensor_info.subdev_id[i]);
break;
case CFG_GET_SENSOR_INIT_PARAMS:
cdata->cfg.sensor_init_params =
*s_ctrl->sensordata->sensor_init_params;
CDBG("%s:%d init params mode %d pos %d mount %d\n", __func__, __LINE__,
cdata->cfg.sensor_init_params.modes_supported,
cdata->cfg.sensor_init_params.position,
cdata->cfg.sensor_init_params.sensor_mount_angle);
break;
case CFG_SET_SLA VE_INFO: {
}
}
此外,点亮camera应用层还需要修改以下文件,之中标红的需要驱动修改。.../proprietary/common/config/device-vendor.mk
.../0208/libchromatix/chromatix_s5k3l1yx/Android.mk
.../chromatix_s5k3l1yx/hfr_120fps/Android.mk
.../hfr_120fps/chromatix_s5k3l1yx_hfr_120fps.c
.../hfr_120fps/chromatix_s5k3l1yx_hfr_120fps.h
.../chromatix_s5k3l1yx/hfr_60fps/Android.mk
.../hfr_60fps/chromatix_s5k3l1yx_hfr_60fps.c
.../hfr_60fps/chromatix_s5k3l1yx_hfr_60fps.h
.../chromatix_s5k3l1yx/hfr_90fps/Android.mk
.../hfr_90fps/chromatix_s5k3l1yx_hfr_90fps.c
.../hfr_90fps/chromatix_s5k3l1yx_hfr_90fps.h
.../chromatix_s5k3l1yx/preview/Android.mk
.../preview/chromatix_s5k3l1yx_preview.c load_chromatix .../preview/chromatix_s5k3l1yx_preview.h
.../libchromatix/chromatix_s5k3l1yx/video/Android.mk
.../video/chromatix_s5k3l1yx_video.c
.../video/chromatix_s5k3l1yx_video.h
.../chromatix_s5k3l1yx/video_hd/Android.mk
.../video_hd/chromatix_s5k3l1yx_video_hd.c
.../video_hd/chromatix_s5k3l1yx_video_hd.h
.../libchromatix/chromatix_s5k3l1yx/zsl/Android.mk
.../chromatix_s5k3l1yx/zsl/chromatix_s5k3l1yx_zsl.c
.../chromatix_s5k3l1yx/zsl/chromatix_s5k3l1yx_zsl.h
.../hardware/actuator/0208/8974/af_main_cam_8.h
.../mm-camera/server/hardware/actuator/actuator.c
.../server/hardware/sensor/s5k3l1yx/s5k3l1yx_u.c
.../server/hardware/sensor/s5k3l1yx/s5k3l1yx_u.h
.../mm-camera/server/hardware/sensor/sensor.c
3.3 兼容问题
与之前的方法相同,还是在kernel读取id,判断camera是否存在,然后上报名字,应用层根据名字加载效果文件,为了避免clock加载失败,在dtsi中配置假地址,在驱动文件中再重写真实地址。