完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
RK3568 Sensor 驱动位于 drivers/media/i2c 目录下。
可以把Sensor 驱动的开发移植概括为以下 5 个部分:
dts 根据硬件的设计,主要是正确配置clk及 pinctl(iomux)、根据原理图设置上电时序所需要的 regulator 及 gpio、增加 port 子节点,与 cif 或者 isp 建立连接:
以gc8034为例: &i2c4 { status = "okay"; gc8034: gc8034@37 { compatible = "galaxycore,gc8034";// 需要与驱动中的匹配字符串一致 status = "okay"; reg = <0x37>;// sensor I2C 设备地址 clocks = <&cru CLK_CIF_OUT>;// sensor clickin 配置 clock-names = "xvclk"; pinctrl-names = "default";// pinctl 设置 pinctrl-0 = <&cif_clk>; reset-gpios = <&gpio3 RK_PB6 GPIO_ACTIVE_LOW>;// reset 管脚分配及有效电平 pwdn-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_LOW>;// power 管脚分配及有效电平 rockchip,grf = <&grf>; rockchip,camera-module-index = <0>;// 模组编号,该编号不要重复 rockchip,camera-module-facing = "back";// 模组朝向,有"back"和"front" // 模组名和 lens 名被用来和 IQ xml 文件做匹配 rockchip,camera-module-name = "RK-CMK-8M-2-v1";// 模组名 rockchip,camera-module-lens-name = "CK8401";// lens 名 /*lens-focus = <&vm149c>; // vcm 驱动设置,支持 AF 时需要有这个设置*/ avdd-supply = <&vcc2v8_dvp>; // sensor 电源配置 dovdd-supply = <&vcc1v8_dvp>; dvdd-supply = <&vcc1v8_dvp>; port { gc8034_out: endpoint { remote-endpoint = <&mipi_in_ucam1>;// mipi dphy 端的 port 名 data-lanes = <1 2 3 4>;// mipi lane 数, 1lane 为 <1>, 4lane 为 <1 2 3 4> }; }; }; }; 驱动 上下电时序 不同 Sensor 对上下电时序要求不同,在 Sensor 厂家提供的 DataSheet 中,一般会有上电时序图,只需要按顺序配置即可。其中_power_on() 即是用来给 Sensor 上电。 上电时序简要说明如下:
代码如下: static int __gc8034_power_on(struct gc8034 *gc8034) { int ret; u32 delay_us; struct device *dev = &gc8034->client->dev; if (!IS_ERR(gc8034->power_gpio)) gpiod_set_value_cansleep(gc8034->power_gpio, 1); usleep_range(1000, 2000); if (!IS_ERR_OR_NULL(gc8034->pins_default)) { ret = pinctrl_select_state(gc8034->pinctrl, gc8034->pins_default); if (ret < 0) dev_err(dev, "could not set pinsn"); } ret = clk_set_rate(gc8034->xvclk, GC8034_XVCLK_FREQ); if (ret < 0) dev_warn(dev, "Failed to set xvclk rate (24MHz)n"); if (clk_get_rate(gc8034->xvclk) != GC8034_XVCLK_FREQ) dev_warn(dev, "xvclk mismatched, modes are based on 24MHzn"); ret = clk_prepare_enable(gc8034->xvclk); if (ret < 0) { dev_err(dev, "Failed to enable xvclkn"); return ret; } if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 1); ret = regulator_bulk_enable(GC8034_NUM_SUPPLIES, gc8034->supplies); if (ret < 0) { dev_err(dev, "Failed to enable regulatorsn"); goto disable_clk; } usleep_range(1000, 1100); if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 0); usleep_range(500, 1000); if (!IS_ERR(gc8034->pwdn_gpio)) gpiod_set_value_cansleep(gc8034->pwdn_gpio, 0); /* 8192 cycles prior to first SCCB transaction */ delay_us = gc8034_cal_delay(8192); usleep_range(delay_us, delay_us * 2); return 0; disable_clk: clk_disable_unprepare(gc8034->xvclk); return ret; } 同样,datasheet 中还会有下电时序(Power Down Sequence),也需要按要求实现, 代码如下: static void __gc8034_power_off(struct gc8034 *gc8034) { int ret; if (!IS_ERR(gc8034->pwdn_gpio)) gpiod_set_value_cansleep(gc8034->pwdn_gpio, 1); clk_disable_unprepare(gc8034->xvclk); if (!IS_ERR(gc8034->reset_gpio)) gpiod_set_value_cansleep(gc8034->reset_gpio, 1); if (!IS_ERR_OR_NULL(gc8034->pins_sleep)) { ret = pinctrl_select_state(gc8034->pinctrl, gc8034->pins_sleep); if (ret < 0) dev_dbg(&gc8034->client->dev, "could not set pinsn"); } if (!IS_ERR(gc8034->power_gpio)) gpiod_set_value_cansleep(gc8034->power_gpio, 0); regulator_bulk_disable(GC8034_NUM_SUPPLIES, gc8034->supplies); } Sensor Regs Init 在 Sensor驱动中,需要定义了 struct sensor_mode ,用来初始化不同的 Sensor mode,即Sensor可以输出不同分辨率的图像、不同的fps等。Mode 包括分辨率(width、height),Mbus Code,max_fps,寄存器初始化列表等。 struct sensor_mode struct gc8034_mode { u32 width;//有效图像宽度 u32 height;//有效图像高度 struct v4l2_fract max_fps;//图像 FPS, denominator/numerator 为 fps u32 hts_def;//默认 HTS,为有效图像宽度 + HBLANK u32 vts_def;//默认 VTS,为有效图像高度 + VBLANK u32 exp_def;//默认曝光时间 const struct regval *reg_list;//寄存器列表 }; static const struct gc8034_mode supported_modes_2lane[] = { { .width = 1632, .height = 1224, .max_fps = { .numerator = 10000, .denominator = 300000, }, .exp_def = 0x09a0, .hts_def = 0x0858 * 2, .vts_def = 0x09c4, .reg_list = gc8034_1632x1224_regs_2lane, }, }; ensor驱动中的 exp_def 、 hts_def 、 vts_def ,从datasheet中查找到对应的寄存器,并从寄存器列表中找到初始化时配置的值即可。 初始化寄存器 /* * Xclk 24Mhz * max_framerate 30fps * mipi_datarate per lane 672Mbps */ static const struct regval gc8034_1632x1224_regs_2lane[] = { /*SYS*/ {0xf2, 0x00}, {0xf4, 0x80}, {0xf5, 0x19}, {0xf6, 0x44}, {0xf8, 0x63}, {0xfa, 0x45}, {0xf9, 0x00}, {0xf7, 0x95}, {0xfc, 0x00}, {0xfc, 0x00}, {0xfc, 0xea}, {0xfe, 0x03}, {0x03, 0x9a}, {0xfc, 0xee}, {0xfe, 0x10}, {0xfe, 0x00}, {0xfe, 0x10}, {0xfe, 0x00}, /*ISP*/ {0xfe, 0x00}, {0x80, 0x10}, {0xad, 0x30}, {0x66, 0x2c}, {0xbc, 0x49}, /*Crop window*/ {0x90, 0x01}, {0x92, BINNING_STARTY}, //crop y {0x94, BINNING_STARTX}, //crop x {0x95, 0x04}, {0x96, 0xc8}, {0x97, 0x06}, {0x98, 0x60}, /*MIPI*/ {0xfe, 0x03}, {0x01, 0x07}, {0x02, 0x03}, {0x04, 0x80}, {0x11, 0x2b}, {0x12, 0xf8}, {0x13, 0x07}, {0x15, 0x10}, //LP mode {0x16, 0x29}, {0x17, 0xff}, {0x18, 0x01}, {0x19, 0xaa}, {0x1a, 0x02}, {0x21, 0x05}, {0x22, 0x06}, {0x23, 0x16}, {0x24, 0x00}, {0x25, 0x12}, {0x26, 0x07}, {0x29, 0x07}, {0x2a, 0x08}, {0x2b, 0x07}, {0xfe, 0x00}, {0x3f, 0x00}, {REG_NULL, 0x00}, }; 寄存器初始化列表,请按厂家提供的直接填入即可。需要注意的是,列表最后用了 REG_NULL 表示结束。注意REG_NULL不要和寄存器地址冲突。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
431 浏览 0 评论
524 浏览 1 评论
1789 浏览 1 评论
3043 浏览 1 评论
synopsys 的design ware:DW_fpv_div,浮点数除法器,默认32位下,想提升覆盖率(TMAX),如果用功能case去提升覆盖率呢?
3771 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-19 09:21 , Processed in 0.710546 second(s), Total 72, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号