天天看點

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);
           
display:kms-panel-4.14kernel

延伸顯示能力識别(Extended display identification data,簡稱EDID)是指螢幕分辨率的資料,包括廠商名稱與序号。一般EDID存在于顯示器的PROM或EEPROM内。一般如要讀取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
           

繼續閱讀