国产精品chinese,色综合天天综合精品网国产在线,成午夜免费视频在线观看,清纯女学生被强行糟蹋小说

    <td id="ojr13"><tr id="ojr13"><label id="ojr13"></label></tr></td>
        • <source id="ojr13"></source>
            <td id="ojr13"><ins id="ojr13"><label id="ojr13"></label></ins></td>

            Article / 文章中心

            kernel驅(qū)動中通過I2C配置圖顯系統(tǒng)各顯示外設(shè)(HDMI/MIPI/DP等)寄存器的實現(xiàn)

            發(fā)布時間:2021-11-29 點擊數(shù):1666

            1. 背景介紹

            在圖顯系統(tǒng)中,各顯示IP(MIPI、HDMI、DP等)或屏幕的寄存器配置,可以通過I2C總線來實現(xiàn)。

            以HDMI PHY芯片為例,分析在HDMI驅(qū)動中如何調(diào)用I2C接口實現(xiàn)HDMI PHY芯片寄存器的訪問。

            2. 設(shè)備樹代碼實現(xiàn)

            在slave設(shè)備的設(shè)備樹結(jié)點中定義需要使用的I2C控制器。

            hdmi: hdmi@12D00000 {
                    compatible = "samsung,exynos4210-hdmi";
            ...
                    phy = <&hdmi_i2c_phy>;
            ...
            };

            而hdmi_i2c_phy從屬于i2c_8。

            i2c_8: i2c@138E0000 {
                    #address-cells = <1>;         #size-cells = <0>;         compatible = "samsung,s3c2440-hdmiphy-i2c";
            ...
                    hdmi_i2c_phy: hdmiphy@38 {
                            compatible = "exynos4210-hdmiphy";
                            reg = <0x38>;
                    };
            };

            上面的hdmi_i2c_phy相當(dāng)于是i2c_8的label索引,通過查看dtb的反匯編文件之后可以確定這一點。

            i2c@138E0000 {
            ...
                    compatible = "samsung,s3c2440-hdmiphy-i2c";
            ...
                    hdmiphy@38 {
                            compatible = "exynos4210-hdmiphy";
                            reg = <0x38>;
                            linux,phandle = <0x43>;
                            phandle = <0x43>;
                    };
            };
            
            hdmi@12D00000 {
                    compatible = "samsung,exynos4212-hdmi";
            ...
                    phy = <0x43>;
            ...
            };

            3.驅(qū)動代碼實現(xiàn)

            在驅(qū)動代碼中,我們需要做的事情是在HDMI驅(qū)動中通過解析設(shè)備樹找到對應(yīng)的I2C驅(qū)動,從而掛載相關(guān)的I2C數(shù)據(jù)傳輸接口函數(shù)。在下面的函數(shù)中主要涉及了3個API,分別是:
            of_find_compatible_node()
            of_parse_phandle()
            of_find_i2c_device_by_node

            static int hdmi_get_phy_io(struct hdmi_context *hdata) {
             const char *compatible_str = "samsung,exynos4212-hdmiphy";
             struct device_node *np;  int ret = 0;
            
             np = of_find_compatible_node(NULLNULL, compatible_str);
             if (!np) {
              np = of_parse_phandle(hdata->dev->of_node, "phy"0);
              if (!np) {
               DRM_ERROR("Failed to find hdmiphy node in device tree\n");
               return -ENODEV;
              }
             }
            
             if (hdata->drv_data->is_apb_phy) {
              hdata->regs_hdmiphy = of_iomap(np, 0);
              if (!hdata->regs_hdmiphy) {
               DRM_ERROR("failed to ioremap hdmi phy\n");
               ret = -ENOMEM;
               goto out;
              }
             } else {
              hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
              if (!hdata->hdmiphy_port) {
               DRM_INFO("Failed to get hdmi phy i2c client\n");
               ret = -EPROBE_DEFER;
               goto out;
              }
             }
            
            out:
             of_node_put(np);
             return ret;
            }

            4. 讀寫寄存器代碼實現(xiàn)

            在通過i2c讀寫寄存器的時候,主要是通過調(diào)用i2c_master_send()這個函數(shù)來實現(xiàn)的。

            static int hdmiphy_reg_write_buf(struct hdmi_context *hdata,
               u32 reg_offset, const u8 *buf, u32 len) {
             if ((reg_offset + len) > 32)
              return -EINVAL;
            
             if (hdata->hdmiphy_port) {
              int ret;
            
              ret = i2c_master_send(hdata->hdmiphy_port, buf, len);
              if (ret == len)
               return 0;
              return ret;
             } else {
              int i;
              for (i = 0; i < len; i++)
               writel(buf[i], hdata->regs_hdmiphy +
                ((reg_offset + i)<<2));
              return 0;
             }
            }

            end