soc平台
|
开发板品牌
|
sdk版本
|
开发平台
|
rv1126
|
firefly
|
20211022
|
ubuntu18.04 64位
|
学嵌入式开发也有一段时间了,本来也是想搞一款音视频编码器产品,出于这个目的,也验证一下自己的能力。
由于现在开发板是现成的了,引出了对应MIPI CSI的两组总线,需要自己做个HDMI转MIPI的模块,自己根据芯片手册,简单设计了一个LT6911UXC的转换模块(调试板有点脏乱)。
image-20230714165528631
整个硬件平台算是搭建完成了。
这里说是移植,而不是开发的原因是,正好手头上有已经比较完美的驱动了。只是硬件平台的改动而已。
一、根据电路在设备树中增加I2C设备
这里设计的是挂载在I2C2上的,所以
&i2c2{
status = "okay";clock-frequency = <100000>;lt6911uxc: lt6911uxc@2b {compatible = "LT6911UXC";reg = <0x2b>;};};复制代码
二、根据源码改设备树
都知道,设备树是描述硬件资源的。既然硬件平台改了,那么对于新的硬件平台当然是要在设备树中加入设备和相关信息了
1. 看源码
源码中有这样一个函数
#ifdef CONFIG_OF
static int lt6911uxc_parse_of(struct lt6911uxc *lt6911uxc){struct device *dev = <6911uxc->i2c_client->dev;struct device_node *node = dev->of_node;struct v4l2_fwnode_endpoint *endpoint;struct device_node *ep;int ret;ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,<6911uxc->module_index);ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,<6911uxc->module_facing);ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,<6911uxc->module_name);ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,<6911uxc->len_name);if (ret) {dev_err(dev, "could not get module information!\n");return -EINVAL;}#if 0lt6911uxc->power_gpio = devm_gpiod_get_optional(dev, "power", //电源控制GPIOD_OUT_LOW);if (IS_ERR(lt6911uxc->power_gpio)) {dev_err(dev, "failed to get power gpio\n");ret = PTR_ERR(lt6911uxc->power_gpio);return ret;}#endiflt6911uxc->reset_gpio = devm_gpiod_get_optional(dev, "reset", //复位引脚GPIOD_OUT_LOW);if (IS_ERR(lt6911uxc->reset_gpio)) {dev_err(dev, "failed to get reset gpio\n");ret = PTR_ERR(lt6911uxc->reset_gpio);return ret;}lt6911uxc->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", //插入检测GPIOD_IN);if (IS_ERR(lt6911uxc->plugin_det_gpio)) {dev_err(dev, "failed to get plugin det gpio\n");ret = PTR_ERR(lt6911uxc->plugin_det_gpio);return ret;}#if 0lt6911uxc->hpd_ctl_gpio = devm_gpiod_get_optional(dev, "hpd-ctl", //热插拔控制GPIOD_OUT_HIGH);if (IS_ERR(lt6911uxc->hpd_ctl_gpio)) {dev_err(dev, "failed to get hpd ctl gpio\n");ret = PTR_ERR(lt6911uxc->hpd_ctl_gpio);return ret;}#endif//获取和配置v4l2相关端点ep = of_graph_get_next_endpoint(dev->of_node, NULL);if (!ep) {dev_err(dev, "missing endpoint node\n");ret = -EINVAL;return ret;}endpoint = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep));if (IS_ERR(endpoint)) {dev_err(dev, "failed to parse endpoint\n");ret = PTR_ERR(endpoint);return ret;}if (endpoint->bus_type != V4L2_MBUS_CSI2 ||endpoint->bus.mipi_csi2.num_data_lanes == 0) {dev_err(dev, "missing CSI-2 properties in endpoint\n");ret = -EINVAL;goto free_endpoint;}#if 1lt6911uxc->xvclk = devm_clk_get(dev, "xvclk"); //如果lt6911的外部时钟是soc提供,则需要进行相关配置if (IS_ERR(lt6911uxc->xvclk)) {dev_err(dev, "failed to get xvclk\n");ret = -EINVAL;goto free_endpoint;}ret = clk_prepare_enable(lt6911uxc->xvclk);if (ret) {dev_err(dev, "Failed! to enable xvclk\n");goto free_endpoint;}#endiflt6911uxc->csi_lanes_in_use = endpoint->bus.mipi_csi2.num_data_lanes;lt6911uxc->bus = endpoint->bus.mipi_csi2;lt6911uxc->enable_hdcp = false;// gpiod_set_value(lt6911uxc->hpd_ctl_gpio, 0);// gpiod_set_value(lt6911uxc->power_gpio, 1);lt6911uxc_reset(lt6911uxc);ret = 0;free_endpoint:v4l2_fwnode_endpoint_free(endpoint);return ret;}复制代码
从整个处理过程中,此函数是在通过devm_gpiod_get_optional这个函数查找设备树中 "power-gpios" , "reset-gpios", "plugin-det-gpios", "hpd-ctl-gpios"相关节点,并进行输入输出模式配置。将返回的结果存储到定义的lt6911uxc私有数据中。
2. 改设备树
根据以上源码,对设备树进行如下配置(根据电路设计,power和HPD的控制这里没有用到,所以这里不做配置)
reset-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_LOW>;
plugin-det-gpios = <&gpio2 RK_PB0 IRQ_TYPE_LEVEL_LOW>;//hpd-ctl-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_LOW>;复制代码
3. 处理函数函数
复位函数
static void lt6911uxc_reset(struct lt6911uxc *lt6911uxc)
{gpiod_set_value(lt6911uxc->reset_gpio, 0);usleep_range(2000, 2100);gpiod_set_value(lt6911uxc->reset_gpio, 1);usleep_range(120*1000, 121*1000);gpiod_set_value(lt6911uxc->reset_gpio, 0);usleep_range(300*1000, 310*1000);}复制代码
插入检测函数
static inline bool tx_5v_power_present(struct v4l2_subdev *sd)
{int val;struct lt6911uxc *lt6911uxc = to_state(sd);val = gpiod_get_value(lt6911uxc->plugin_det_gpio);v4l2_dbg(1, debug, sd, "%s plug det: %s!\n", __func__,(val > 0) ? "int" : "out");return (val > 0);}static irqreturn_t plugin_detect_irq_handler(int irq, void *dev_id){struct lt6911uxc *lt6911uxc = dev_id;struct v4l2_subdev *sd = <6911uxc->sd;/* control hpd output level after 25ms */// schedule_delayed_work(<6911uxc->delayed_work_enable_hotplug,// HZ / 40);tx_5v_power_present(sd);return IRQ_HANDLED;}复制代码
三、根据其他摄像头配置完善设备树
&i2c2{
status = "okay";clock-frequency = <100000>;lt6911uxc: lt6911uxc@2b {compatible = "LT6911UXC";reg = <0x2b>;clocks = <&cru CLK_MIPICSI_OUT>;clock-names = "xvclk";interrupt-parent=<&gpio3>;interrupts=;pinctrl-names = "default";pinctrl-0 = <<6911uxc_pin>;reset-gpios = <&gpio4 RK_PA1 GPIO_ACTIVE_LOW>;plugin-det-gpios = <&gpio2 RK_PB0 IRQ_TYPE_LEVEL_LOW>;// hpd-ctl-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_LOW>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "back";rockchip,camera-module-name = "hdmi_in"; //摄像头名称rockchip,camera-module-lens-name = "lt6911uxc"; //摄像头镜头port { //v4l2端点配置ucam_out0: endpoint {remote-endpoint = <&mipi_in_ucam0>;data-lanes = <1 2 3 4>;};};};};复制代码
四、其他设备树配置
&csi_dphy0 {
status = "okay";ports {#address-cells = <1>;#size-cells = <0>;port@0 {reg = <0>;#address-cells = <1>;#size-cells = <0>;/*mipi_in_ucam0: endpoint@1 {reg = <1>;remote-endpoint = <&ucam_out0>;data-lanes = <1 2 3 4>;};*/mipi_in_ucam0: endpoint@1 {reg = <1>;remote-endpoint = <&ucam_out0>;data-lanes = <1 2 3 4>;};};port@1 {reg = <1>;#address-cells = <1>;#size-cells = <0>;csidphy0_out: endpoint@0 {reg = <0>;remote-endpoint = <&mipi_csi2_input>;data-lanes = <1 2 3 4>;};};};};&mipi_csi2 {status = "okay";ports {#address-cells = <1>;#size-cells = <0>;port@0 {reg = <0>;#address-cells = <1>;#size-cells = <0>;mipi_csi2_input: endpoint@1 {reg = <1>;remote-endpoint = <&csidphy0_out>;data-lanes = <1 2 3 4>;};};port@1 {reg = <1>;#address-cells = <1>;#size-cells = <0>;mipi_csi2_output: endpoint@0 {reg = <0>;remote-endpoint = <&cif_mipi_in>;data-lanes = <1 2 3 4>;};};};};复制代码
五、总结
以上也就配置完成了,具体调试过程可以参看我的另一篇文章
RK628底层调试,使用V4L2调试工具抓图-面包板社区 (eet-china.com)
rtsp获取demo可以使用瑞芯微SDK自带的
SDK/external/rkmedia/examples/rkmedia_vi_venc_rtsp_test.c
文章评论(0条评论)
登录后参与讨论