天天看点

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
           

继续阅读