国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

驅動之路#04:LCD 驅動程序分析(基于RK3576)

BSP調試從0到1 ? 來源:嵌入式分享 ? 作者:嵌入式分享 ? 2026-02-17 08:20 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

題圖:河北太行山脈,山頭密密麻麻都被太陽能板覆蓋了。

歡迎關注,每周更新!?

本合集分享的是,我當初學習Linux驅動的來時路——《《驅動之路》開篇:自序&前言》。

正文

在實際工作中,雖然并不需要我們從零編寫 LCD 驅動程序,但必須掌握 LCD 驅動框架 —— 這是分析現有驅動、定位問題,以及在必要時修改驅動以適配硬件或需求的必修課。

分析之前,首先需要掌握字符設備驅動的基本框架,看前面文章《驅動之路#01:Hello World!》。LCD 驅動本質上也是字符設備驅動,理解了字符設備驅動的框架,有助于分析 LCD 驅動程序。

下面我們就運用前面掌握的字符設備驅動基本框架,以 RK3576 平臺的 panel-simple.c 為例,淺淺分析 LCD 驅動。

驅動位置:kernel-6.1/drivers/gpu/drm/panel/panel-simple.c

如何閱讀驅動程序,準確說是如何閱讀字符設備驅動程序?閱讀一個字符設備驅動程序,應該從它的入口函數開始看。

看到 panel-simple.c 的入口函數*register() 注冊了 3 個驅動,說明該驅動程序同時兼容DPIDSI和SPI接口連接的 panel。

wKgZO2mTtV6ABC1gAADoM4XiIH8808.png

拿 panel_simple_dsi_driver 舉例分析,繼續往下看。當 driver 與 device(即 dts) 的 compatible 屬性匹配就會調用 panel_simple_dsi_probe 函數。

wKgZO2mTtV6AV8ayAAHNHHsufxM945.png

只有我們弄清楚panel_simple_dsi_probe函數的具體操作就基本了解了panel_simple_dsi_driver驅動,這就是分析字符設備驅動程序的大致流程。

接下來,分析 panel_simple_dsi_probe 函數,直接看代碼注釋。

/** MIPI-DSI 面板探測函數* 負責初始化DSI接口的面板設備*/staticintpanel_simple_dsi_probe(structmipi_dsi_device *dsi){ /* 局部變量定義 */ structpanel_simple *panel;   // 通用面板數據結構 structdevice *dev = &dsi->dev; // 獲取設備指針,簡化后續訪問 conststructpanel_desc_dsi *desc;// DSI面板描述符(預定義或動態) structpanel_desc_dsi *d;    // 動態分配的描述符指針 conststructof_device_id *id; // 設備樹匹配結果 interr;            // 錯誤碼 /* 1. 設備樹匹配 - 檢查設備是否在驅動支持列表中 */  id = of_match_node(dsi_of_match, dsi->dev.of_node); if(!id)   return-ENODEV; // 設備不在支持列表中,返回設備不存在錯誤 /* 2. 面板描述符處理 */ if(!id->data) {   /* 情況A: 設備樹中定義了自定義面板,沒有預定義描述符 */   // 動態分配DSI面板描述符內存    d = devm_kzalloc(dev,sizeof(*d), GFP_KERNEL);   if(!d)     return-ENOMEM; // 內存分配失敗   /* 從設備樹節點解析面板參數 */    err = panel_simple_dsi_of_get_desc_data(dev, d);   if(err) {      dev_err(dev,"failed to get desc data: %dn", err);     returnerr; // 參數解析失敗    }  } /* 注意: 如果 id->data 不為空,表示使用預定義的描述符,跳過動態分配 */ /* 3. 選擇最終使用的描述符 */  desc = id->data ? id->data : d; // 優先使用預定義,否則使用動態解析的描述符 /* 4. 調用通用面板探測函數進行基礎初始化 */  err = panel_simple_probe(&dsi->dev, &desc->desc); if(err dsi = dsi;       // 將DSI設備指針保存到面板結構中,建立雙向關聯 /* 6. 背光設備處理 */ if(!panel->base.backlight) {   /* 如果面板沒有背光設備,注冊一個DCS背光設備 */   structbacklight_properties props; // 背光屬性結構   /* 初始化背光屬性 */    memset(&props,0,sizeof(props));    props.type = BACKLIGHT_RAW;   // 背光類型:原始模式    props.brightness =255;     // 初始亮度:最大值    props.max_brightness =255;   // 最大亮度:255級   /* 注冊背光設備 */    panel->base.backlight =        devm_backlight_device_register(dev, dev_name(dev),                       dev, panel, &dcs_bl_ops,                       &props);   /* 錯誤處理 */   if(IS_ERR(panel->base.backlight)) {      err = PTR_ERR(panel->base.backlight);      dev_err(dev,"failed to register dcs backlight: %dn", err);     returnerr; // 背光設備注冊失敗    }  } /* 注意: 如果面板已有背光設備(如通過設備樹引用),則跳過此步驟 */ /* 7. 配置DSI主機控制器參數 */  dsi->mode_flags = desc->flags; // 設置DSI工作模式標志  dsi->format = desc->format;   // 設置像素數據格式  dsi->lanes = desc->lanes;    // 設置數據通道數量 /* 8. 將面板附加到DSI主機 */  err = mipi_dsi_attach(dsi); if(err) {   /* 附件失敗時的清理工作 */   structpanel_simple *panel = mipi_dsi_get_drvdata(dsi);    drm_panel_remove(&panel->base); // 從DRM子系統移除面板  } /* 9. 返回執行結果 */ returnerr; // 成功返回0,失敗返回錯誤碼}

我們在設備樹中定義的屏參以及mipi 屏幕相關初始化代碼。

wKgZO2mTtV6AH792AAK8_dj-zhw331.png

最終是通過函數 panel_simple_dsi_of_get_desc_data()和 panel_simple_of_get_desc_data()獲取到的。

wKgZO2mTtV6ACTP8AARQ5GMJv50168.png

至此,mipi-dsi 屏幕驅動分析完畢!能分析閱讀整體驅動框架和函數調用流程就行,不需要花大量時間和精力去解讀每行代碼解讀,AI時代沒多大意義。

最后附上兩個比較重要的函數,供閱讀參考。

附錄:static int panel_simple_dsi_of_get_desc_data(struct device *dev,          struct panel_desc_dsi *desc){  struct device_node *np = dev->of_node;  u32val;  int err; // 1. 首先解析通用面板參數  err = panel_simple_of_get_desc_data(dev, &desc->desc); if(err)   returnerr; // 2. 設置連接器類型為DSI  desc->desc.connector_type = DRM_MODE_CONNECTOR_DSI; // 3. 從dts解析DSI特有參數 if(!of_property_read_u32(np,"dsi,flags", &val))    desc->flags =val; if(!of_property_read_u32(np,"dsi,format", &val))    desc->format =val; if(!of_property_read_u32(np,"dsi,lanes", &val))    desc->lanes =val; return0;}函數 panel_simple_dsi_of_get_desc_data( )中調用 panel_simple_dsi_of_get_desc_data( )獲取面板 desc_data。static int panel_simple_of_get_desc_data(struct device *dev,          struct panel_desc *desc){  struct device_node *np = dev->of_node;  u32 bus_flags; constvoid *data;  int len;  int err; // 1. 解析顯示時序 if(of_child_node_is_present(np,"display-timings")) {    struct drm_display_mode *mode;    mode = devm_kzalloc(dev, sizeof(*mode), GFP_KERNEL);   if(!mode)     return-ENOMEM;   // 從設備樹解析DRM顯示模式   if(!of_get_drm_display_mode(np, mode, &bus_flags,            OF_USE_NATIVE_MODE)) {      desc->modes = mode;      desc->num_modes =1;      desc->bus_flags = bus_flags;    }  }elseif(of_child_node_is_present(np,"panel-timing")) {    struct display_timing *timing;    struct videomode vm;    timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL);   if(!timing)     return-ENOMEM;   // 從設備樹解析顯示時序   if(!of_get_display_timing(np,"panel-timing", timing)) {      desc->timings = timing;      desc->num_timings =1;     // 轉換時序標志為總線標志      bus_flags =0;      vm.flags = timing->flags;      drm_bus_flags_from_videomode(&vm, &bus_flags);      desc->bus_flags = bus_flags;    }  } // 2. 解析基本面板屬性 if(desc->num_modes || desc->num_timings) {    of_property_read_u32(np,"bpc", &desc->bpc);     // 每顏色位數    of_property_read_u32(np,"connector-type", &desc->connector_type);    of_property_read_u32(np,"bus-format", &desc->bus_format);// 總線格式    of_property_read_u32(np,"width-mm", &desc->size.width); // 物理寬度    of_property_read_u32(np,"height-mm", &desc->size.height);// 物理高度  } // 3. 解析時序延遲參數  of_property_read_u32(np,"prepare-delay-ms", &desc->delay.prepare);  of_property_read_u32(np,"enable-delay-ms", &desc->delay.enable);  of_property_read_u32(np,"disable-delay-ms", &desc->delay.disable);  of_property_read_u32(np,"unprepare-delay-ms", &desc->delay.unprepare);  of_property_read_u32(np,"reset-delay-ms", &desc->delay.reset);  of_property_read_u32(np,"init-delay-ms", &desc->delay.init); // 4. 解析初始化序列 data= of_get_property(np,"panel-init-sequence", &len); if(data) {    desc->init_seq = devm_kzalloc(dev, sizeof(*desc->init_seq), GFP_KERNEL);   if(!desc->init_seq)     return-ENOMEM;   // 解析初始化命令序列    err = panel_simple_parse_cmd_seq(dev,data, len, desc->init_seq);   if(err) {      dev_err(dev,"failed to parse init sequencen");     returnerr;    }  } // 5. 解析退出序列 data= of_get_property(np,"panel-exit-sequence", &len); if(data) {    desc->exit_seq = devm_kzalloc(dev, sizeof(*desc->exit_seq), GFP_KERNEL);   if(!desc->exit_seq)     return-ENOMEM;   // 解析退出命令序列    err = panel_simple_parse_cmd_seq(dev,data, len, desc->exit_seq);   if(err) {      dev_err(dev,"failed to parse exit sequencen");     returnerr;    }  } return0;}

(完)

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • lcd
    lcd
    +關注

    關注

    36

    文章

    4615

    瀏覽量

    177203
  • 驅動程序
    +關注

    關注

    19

    文章

    869

    瀏覽量

    50456
  • rk3576
    +關注

    關注

    1

    文章

    265

    瀏覽量

    1546
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    硬核進階:RK3576 Android15?驅動與系統開發實戰指南

    RK3576 探索之旅】系列文章導航及功能全景介紹(基于android14) 之前有出過系列的文章,但這是自己公司定制項目,暫時沒有相關硬件,有需求可以私信我,這個系列主要還是驅動的開發,接下來
    的頭像 發表于 01-26 22:29 ?627次閱讀
    硬核進階:<b class='flag-5'>RK3576</b> Android15?<b class='flag-5'>驅動</b>與系統開發實戰指南

    迅為RK3576對比RK3568:AI算力與接口的全面躍遷

    迅為RK3576對比RK3568:AI算力與接口的全面躍遷
    的頭像 發表于 12-22 15:24 ?1589次閱讀
    迅為<b class='flag-5'>RK3576</b>對比<b class='flag-5'>RK</b>3568:AI算力與接口的全面躍遷

    迅為如何在RK3576上部署YOLOv5;基于RK3576構建智能門禁系統

    迅為如何在RK3576開發板上部署YOLOv5;基于RK3576構建智能門禁系統
    的頭像 發表于 11-25 14:06 ?1790次閱讀
    迅為如何在<b class='flag-5'>RK3576</b>上部署YOLOv5;基于<b class='flag-5'>RK3576</b>構建智能門禁系統

    RK3576驅動高端顯控系統升級:多屏拼控與AI視覺融合解決方案

    下達任務指令,副屏監測 AI 分析結果,大屏實時展示各區域畫面與運行狀態,真正實現 “一屏決策,多屏聯動”。 八路攝像頭輸入:實現多源視頻融合與 AI 識別RK3576 原生支持八路攝像頭輸入
    發表于 11-21 17:51

    【作品合集】米爾RK3576開發板測評

    米爾RK3576開發板測評作品合集 產品介紹: RK3576 是瑞芯微一款面向AI市場推出的高性能處理器,它配備了四核Cortex-A72和四 核Cortex-A53 的 CPU,集成了6TOPS
    發表于 09-11 10:19

    【作品合集】靈眸科技EASY EAI Orin Nano(RK3576)開發板測評

    【EASY EAI Orin Nano(RK3576)開發板試用體驗】01-開箱報告及開發環境準備 【EASY EAI Orin Nano(RK3576)開發板試用體驗】02-拓展空間及內核分析
    發表于 09-09 09:59

    瑞芯微RK3576RK3576S有什么區別,性能參數配置與型號差異解析

    瑞芯微第二代8nm高性能AIOT平臺RK3576家族再添新成員-RK3576S,先說結論:相較主型號的RK3576/RK3576J,性能略有縮減,而功耗有所降低。主要應用于商顯終端、智
    的頭像 發表于 08-14 23:57 ?2366次閱讀
    瑞芯微<b class='flag-5'>RK3576</b>與<b class='flag-5'>RK3576</b>S有什么區別,性能參數配置與型號差異解析

    RK這2款旗艦芯片RK3588 PK RK3576,誰是最優選

    在 AI 邊緣計算領域,瑞芯微的 RK3588 和 RK3576 都是備受矚目的處理器。在中國半導體產業的版圖中,瑞芯微作為國內 SoC 芯片領跑者,憑借其在處理器芯片設計領域的深厚積累和持續創新
    發表于 07-10 18:24

    Mpp支持RK3576

    想問下,https://github.com/rockchip-linux/mpp這里面支持RK3576么,看介紹沒有提到說支持RK3576 目前是買了個rk3576的機頂盒,搭載了安卓14,想做安卓視頻硬解。
    發表于 06-13 15:35

    RK3576 vs RK3588:為何越來越多的開發者轉向RK3576

    (圖形性能更強) 分析RK3576 的 A72+A53+M0 組合 在能效比上更優,適合需要長時間運行的設備(如 IoT、平板)。 RK3588 的 A76 架構 單核性能更強,適合高性能計算場景(如
    發表于 05-30 08:46

    適配多種系統,米爾瑞芯微RK3576核心板解鎖多樣化應用

    米爾電子發布的基于瑞芯微 RK3576 核心板和開發板,具備高性能數據處理能力、領先的AI智能分析功能、多樣化的顯示與操作體驗以及強大的擴展性與兼容性,適用于多種應用場景。目前米爾電子為
    發表于 05-23 16:07

    基于RK3576開發板的人臉識別算法

    RK3576開發板展示人臉識別算法例程和API說明
    的頭像 發表于 05-07 16:48 ?2734次閱讀
    基于<b class='flag-5'>RK3576</b>開發板的人臉識別算法

    基于RK3576開發板的RTC使用說明

    文章主要展示RK3576開發板的RTC信息和快速上手例程
    的頭像 發表于 05-07 15:04 ?2227次閱讀
    基于<b class='flag-5'>RK3576</b>開發板的RTC使用說明

    基于RK3576開發板的PWN使用說明

    RK3576開發板使用PWN教程及Demo
    的頭像 發表于 05-07 14:07 ?2256次閱讀
    基于<b class='flag-5'>RK3576</b>開發板的PWN使用說明

    基于RK3576開發板的TF卡槽使用說明

    RK3576開發板使用TF卡槽
    的頭像 發表于 05-07 09:24 ?1942次閱讀
    基于<b class='flag-5'>RK3576</b>開發板的TF卡槽使用說明