display:kms-panel-4.14kernel

Panel硬件上對應屏幕本身。

https://elixir.bootlin.com/linux/latest/source/include/drm/drm_panel.h

Makefile

drm-$(CONFIG_DRM_PANEL) += drm_panel.o

drm_kms_helper-y:drm_panel_helper.o               沒找到對應函數

drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o

obj-y           += panel/
 

 

drm_panel.c + drm_panel.h

void drm_panel_init(struct drm_panel *panel, struct device *dev,
		    const struct drm_panel_funcs *funcs,
		    int connector_type);

int drm_panel_add(struct drm_panel *panel);
void drm_panel_remove(struct drm_panel *panel);

int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector);
void drm_panel_detach(struct drm_panel *panel);

int drm_panel_prepare(struct drm_panel *panel);
int drm_panel_unprepare(struct drm_panel *panel);

int drm_panel_enable(struct drm_panel *panel);
int drm_panel_disable(struct drm_panel *panel);

int drm_panel_get_modes(struct drm_panel *panel, struct drm_connector *connector);

struct drm_panel *of_drm_find_panel(const struct device_node *np);
主要是對軟件函數的最終實現。功能如函數名。

static LIST_HEAD(panel_list);//結合這個panel_list,可以知道panel是存在一個list裏面,init,add,remove等等都
圍繞這個list做操作;剩下的操作則是圍繞着panel->funcs

bridge/panel.c

struct panel_bridge {
    struct drm_bridge bridge;
    struct drm_connector connector;
    struct drm_panel *panel;
    u32 connector_type;
};
這個結構體包含了從主芯片出來的所有硬件抽象

代碼包含一些獲取結構體的container_of的封裝

struct panel_bridge *drm_bridge_to_panel_bridge
struct panel_bridge *drm_connector_to_panel_bridge

獲取mode模式

static const struct drm_connector_helper_funcs
panel_bridge_connector_helper_funcs = {
    .get_modes = panel_bridge_connector_get_modes,
};

panel_bridge_connector_get_modes
最終調用drm_panel_get_mode,回調drm_panel_funcs裏面的getmodes,描述是:
@get_modes: add modes to the connector that the panel is attached to and return the number of modes added

另外是connector_funs和bridge_funcs的回調函數

static const struct drm_connector_funcs panel_bridge_connector_funcs = {
    .reset = drm_atomic_helper_connector_reset,
    .fill_modes = drm_helper_probe_single_connector_modes,
    .destroy = drm_connector_cleanup,
    .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
    .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};

static const struct drm_bridge_funcs panel_bridge_bridge_funcs = {
    .attach = panel_bridge_attach,
    .detach = panel_bridge_detach,
    .pre_enable = panel_bridge_pre_enable,
    .enable = panel_bridge_enable,
    .disable = panel_bridge_disable,
    .post_disable = panel_bridge_post_disable,
};
Bridge的這些回調。一部分是drm_panel.c裏面的實現方法如:
panel_bridge_detach -->drm_panel_detach;

panel_bridge_attach完成drm_connector_init+drm_connector_helper_add+drm_mode_connector_attach_encoder
+drm_panel_attact四步操作。
實現connector的完整初始化並將panel與connector,encoder與connector鏈接起來。

另外提供了

drm_panel_bridge_add
drm_panel_bridge_remove
實現struct panel_bridge結構體的填充與釋放。
調用drm_bridge_add;drm_bridge_remove

devm_drm_panel_bridge_release
devm_drm_panel_bridge_add
後兩者其實是前兩者的封裝。操作更加嚴密安全。

panel/

主要的部分:drm結構體以及方法結構體

 * struct drm_panel_funcs - perform operations on a given panel
 * @disable: disable panel (turn off back light, etc.)
 * @unprepare: turn off panel
 * @prepare: turn on panel and perform set up
 * @enable: enable panel (turn on back light, etc.)
 * @get_modes: add modes to the connector that the panel is attached to and
 * return the number of modes added
 * @get_timings: copy display timings into the provided array and return
 * the number of display timings available

struct drm_panel_funcs {
	int (*disable)(struct drm_panel *panel);
	int (*unprepare)(struct drm_panel *panel);
	int (*prepare)(struct drm_panel *panel);
	int (*enable)(struct drm_panel *panel);
	int (*get_modes)(struct drm_panel *panel);
	int (*get_timings)(struct drm_panel *panel, unsigned int num_timings,
			   struct display_timing *timings);
};
/**
 * struct drm_panel - DRM panel object
 * @drm: DRM device owning the panel
 * @connector: DRM connector that the panel is attached to
 * @dev: parent device of the panel
 * @link: link from panel device (supplier) to DRM device (consumer)
 * @funcs: operations that can be performed on the panel
 * @list: panel entry in registry
 */
struct drm_panel {
	struct drm_device *drm;
	struct drm_connector *connector;
	struct device *dev;
	const struct drm_panel_funcs *funcs;
	struct list_head list;
};

 

實現放在drm/panel/panel_simple.c裏面。作爲外設的移植者如果有用到應該可以改寫。

查看drm_panel_funcs可以發現基本是控制背光,屏幕本身外設的一些操作。get_mode和get_timings一般就是從其他地方獲取長寬,timing等參數。各家實現大同小異。除此之外還有一些如add.init.detach.attach等方法。具體要查看include/drm/drm_panel.h

 

drm_panel.c是基礎。bridge/panel.c是對bridge,panel,connector,encoder的銜接。

 

Qcom

Makefile

msm_drm-y := dp/dp_panel.o

msm_drm-$(CONFIG_DRM_MSM_DSI_STAGING) := dsi-staging/dsi_panel.o

 

DP接口相關名稱

dp/dp_panel.c & dp/dp_panel.h

struct dp_panel_info
struct dp_display_mode
enum dp_lane_count
struct dp_panel    //完全的對dp的抽象。下圖中的大部分元器件均有抽象結構放在dp_panel裏面。也抽象硬件工作方式方法。
struct dp_panel_in
struct dp_dsc_caps
struct dp_audio
struct dp_tu_calc_input
struct dp_vc_tu_mapping_table


static inline bool is_link_rate_valid(u32 bw_code)   
validates the link rate;Returns true if the requested link rate is supported.

static inline bool is_lane_count_valid(u32 lane_count)
struct dp_panel *dp_panel_get(struct dp_panel_in *in);
void dp_panel_put(struct dp_panel *dp_panel);
void dp_panel_calc_tu_test(struct dp_tu_calc_input *in,
struct dp_vc_tu_mapping_table *tu_table);

延伸顯示能力識別(Extended display identification data,簡稱EDID)是指螢幕分辨率的資料,包括廠商名稱與序號。一般EDID存在於顯示器PROMEEPROM內。一般如要讀取EDID都是透過I2C,slave address是0x50;在Linux平臺上也可以看到raw EDID的十六進制格式,只要你執行 "xrandr --verbose"。

wiki摘錄

dp_panel_get 主要init函數,填充大量dp有關數據,以及在dp-panel結構體中定義的大量方法。最終通過結構體指針掛上connector

dp_panel_init_panel_info
1. 通過 drm_dp_dpcd_writeb :write a single byte to the DPCD,發送power相關指令。
2. drm_dp_link_probe 通過drm_dp_dpcd_read :read a series of bytes from the DPCD,讀取相關寄存器,
設置link的傳輸速率,確認版本,設置datalane數量。link可以傳輸視頻信號以及音頻信號。相關結構體爲drm_dp_link

要弄清楚dp_panel裏面的函,需要對dp接口內部的結構操作有了解。

DP接口相關名稱

上述這篇文章以及參考文章有必要了解。

 

dsi-staging/dsi_panel.c &dsi-staging/dsi_panel.h

struct dsi_panel對dsipanel硬件的抽象
dsi_panel_/pre_disable/disable/unprepare/post_unprepare :dsi_panel_tx_cmd_set對芯片寄存器操作,隨後下電
dsi_panel_/enabel/post_enabel/prepare/pre_prepare :dsi_panel_tx_cmd_set對芯片寄存器操作,隨後上電
dsi_panel_/switch/post_switch :dsi_panel_tx_cmd_set對芯片寄存器操作,設置timing
dsi_panel_drv_init:regulator_get+pinctrl+gpio+bl_register 配置

dis_panel_get:解析devicetree獲取相關參數硬件配置。最後執行drm_panel_init [解析參數+初始化硬件]

int dsi_panel_get_mode[參數有dsi-panel,dsi-display-mode]:解析dts

 

顯示屏panel的驅動基本就是:芯片本身,背光,電源管理。

dsi相關名詞QCOM

file:lm80-p0598-2_apq8064e_dsi_programing_gd.pdf

720P HD 720p, 720 progressive scan or non-interlaced horizontal lines high definition
APQ Qualcomm ® Application-only Processor
BLLP Banking or Low-Power Interval
DCS Display Command Set
DSI Display Serial Interface
EMI Electromagnetic Interference
ESC Electronic Speed Controller
fps Frames per second
FWVGA Full-width VGA
GPIO General Purpose Input/Output
HFP Horizontal-sync front porch
HSA Horizontal Sync Active
HVGA Half-size Video Graphics Array
IRQ Interupt Request
LCD Liquid Crystal Display
LCDC Liquid Crystal Display Controller
LCM Liquid Cystral Module
LP Low Power
MDP Mobile Display Processor
MIPI Mobile Industry Processor Interface
MMSS Multimedia Subsystem
PLL Phase Lock Loop
PCLK Pixel Clock
PHY Physical Layer
QHD 960x540 resolution
QVGA Quarter Video Graphics Array, 320 x 240 image resolution
RAM Random Access Memory
RGB Red-Green-Blue
SVGA Super Video Graphics Array (1024 x 768)
TCXO Temperature-Compensated Crystal Oscillator
TE Tearing Effect
VCO Voltage-Controlled Oscillator
VE Vertical Sync End
VGA Video Graphics Array (640 x 480 image resolution)
VS Vertical Sync Start
WQVGA Wide Quarter Video Graphics Array, 320 x 240 image resolution
WSVGA Wide Super VGA, 1024 x 576/600
WVGA 800 x 480 resolution
WXGA, WXGA+ Wide Extended Graphics Array, 1280 x 768, 1440 x 900
XGA Extended Graphics Array, 1024 x 768

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章