文档视界 最新最全的文档下载
当前位置:文档视界 › 8974平台camera模块设计方案

8974平台camera模块设计方案

<8974_LUS7321>

Camera模块设计方案

拟制: 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中配置假地址,在驱动文件中再重写真实地址。

相关文档