uboot drm框架

drm概念

drm显示通路

CRTC: 显示控制器, 在 rockchip 平台是 SOC 内部 VOP(部分文档也称为 LCDC)模块的抽象;
Plane: 图层, 在 rockchip 平台是 SOC 内部 VOP(LCDC)模块 win 图层的抽象;
Encoder: 输出转换器, 指 RGB、 LVDS、 DSI、 eDP、 HDMI、 CVBS、 VGA 等显示接口;
Connector: 连接器, 指 encoder 和 panel 之间交互的接口部分;
Bridge: 桥接设备, 一般用于注册 encoder 后面另外再接的转换芯片, 如 DSI2HDMI 转换芯片。
Panel: 泛指屏, 各种 LCD、 HDMI 等显示设备的抽象;
GEM: buffer 管理和分配,类似 android 下的 ion。

其中bridge部分,当平台无对应 显示接口使用转换芯片

crtc控制器

Z:\RV1109\u-boot\drivers\video\drm\rockchip_crtc.c

//注册vop驱动
U_BOOT_DRIVER(rockchip_vop) = {.name   = "rockchip-vop",.id = UCLASS_VIDEO_CRTC,.of_match = rockchip_vop_ids,.bind    = rockchip_vop_bind,.probe = rockchip_vop_probe,
};
//通过of_match 匹配设备rockchip_vop_ids,1109和1126是一样通用的.compatible = "rockchip,rv1126-vop",.data = (ulong)&rv1126_vop_data,
//rv1126_vop 这个是1126平台的vop驱动设置了vop的一些参数寄存器等等,rockchip_vop_funcs是crtc vop的初始化之类的func
static const struct rockchip_crtc rv1126_vop_data = {.funcs = &rockchip_vop_funcs,.data = &rv1126_vop,
};const struct rockchip_crtc_funcs rockchip_vop_funcs = {.preinit = rockchip_vop_preinit,.init = rockchip_vop_init,.set_plane = rockchip_vop_set_plane,.prepare = rockchip_vop_prepare,.enable = rockchip_vop_enable,.disable = rockchip_vop_disable,.fixup_dts = rockchip_vop_fixup_dts,.send_mcu_cmd = rockchip_vop_send_mcu_cmd,
};

panel

panel部分的控制流程

Z:\RV1109\u-boot\drivers\video\drm\rockchip_panel.c

panel的控制结构体如电源脚struct rockchip_panel_priv {bool prepared;bool enabled;struct udevice *power_supply;struct udevice *backlight;struct gpio_desc enable_gpio;struct gpio_desc reset_gpio;int cmd_type;struct gpio_desc spi_sdi_gpio;struct gpio_desc spi_scl_gpio;struct gpio_desc spi_cs_gpio;
};
panel的参数结构体struct rockchip_panel_plat {bool power_invert;u32 bus_format;unsigned int bpc;struct {unsigned int prepare;unsigned int unprepare;unsigned int enable;unsigned int disable;unsigned int reset;unsigned int init;} delay;struct rockchip_panel_cmds *on_cmds;struct rockchip_panel_cmds *off_cmds;
};
panel的配置及连接状态
struct rockchip_panel {struct udevice *dev;u32 bus_format;unsigned int bpc;const struct rockchip_panel_funcs *funcs;const void *data;struct display_state *state;
};
//display 的结构体包含连接信息及状态 log信息
struct display_state {struct list_head head;const void *blob;ofnode node;struct crtc_state crtc_state;struct connector_state conn_state;struct panel_state panel_state;char ulogo_name[30];char klogo_name[30];struct logo_info logo;int logo_mode;int charge_logo_mode;void *mem_base;int mem_size;int enable;int is_init;int is_enable;
}probe流程reset、电源脚申明gpio_request_by_name(dev, "enable-gpios", 0,&priv->enable_gpio, GPIOD_IS_OUT);gpio_request_by_name(dev, "reset-gpios", 0,&priv->reset_gpio, GPIOD_IS_OUT);uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,"backlight", &priv->backlight);uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,"power-supply", &priv->power_supply);//读取配置发送屏参的方式,有spi、mcu和默认的屏dev_read_string_index(dev, "rockchip,cmd-type", 0, &cmd_type);//注册panel_function,用于屏的初始化 enable之类panel->funcs = &rockchip_panel_funcs;static const struct rockchip_panel_funcs rockchip_panel_funcs = {.init = panel_simple_init,.prepare = panel_simple_prepare,.unprepare = panel_simple_unprepare,.enable = panel_simple_enable,.disable = panel_simple_disable,.getid = panel_simple_getid,
};
//把panel的总线格式赋值到连接接口的值
static void panel_simple_init(struct rockchip_panel *panel)
{struct display_state *state = panel->state;struct connector_state *conn_state = &state->conn_state;conn_state->bus_format = panel->bus_format;
}
//panel上电准备
panel_simple_prepare//panel下电准备panel_simple_unprepare//enable  panelpanel_simple_enable//disable panelpanel_simple_disable//get  panel screen id,兼容多个屏,在mipi_dsi_get_screen_id做屏的兼容panel_simple_getidreturn  mipi_dsi_get_screen_id

connect

这部分是encoder 连接到panel,这里讲解平台用到mipi

//mipi
U_BOOT_DRIVER(dw_mipi_dsi) = {.name = "dw_mipi_dsi",.id = UCLASS_DISPLAY,.of_match = dw_mipi_dsi_ids,.probe = dw_mipi_dsi_probe,.bind = dw_mipi_dsi_bind,.priv_auto_alloc_size = sizeof(struct dw_mipi_dsi),.per_child_platdata_auto_alloc_size = sizeof(struct mipi_dsi_device),.platdata_auto_alloc_size = sizeof(struct mipi_dsi_host),.child_post_bind = dw_mipi_dsi_child_post_bind,.child_pre_probe = dw_mipi_dsi_child_pre_probe,
};
//通过of_match 匹配平台的dw_mipi_dsi_ids,获取到rockchip_connector的data和func,fun是connect模块的功能函数,通过fun与对应的pannel连接.compatible = "rockchip,rv1126-mipi-dsi",.data = (ulong)&rv1126_mipi_dsi_driver_data,static const struct rockchip_connector rv1126_mipi_dsi_driver_data = {.funcs = &dw_mipi_dsi_connector_funcs,.data = &rv1126_mipi_dsi_plat_data,
};static const struct rockchip_connector_funcs dw_mipi_dsi_connector_funcs = {.init = dw_mipi_dsi_connector_init,.prepare = dw_mipi_dsi_connector_prepare,.unprepare = dw_mipi_dsi_connector_unprepare,.enable = dw_mipi_dsi_connector_enable,.disable = dw_mipi_dsi_connector_disable,
};

display子系统

display子系统流程

//Device information used by the video uclass
struct video_priv {/* Things set up by the driver: */ushort xsize;ushort ysize;ushort rot;enum video_log2_bpp bpix;const char *vidconsole_drv_name;int font_size;/** Things that are private to the uclass: don't use these in the* driver*/void *fb;int fb_size;int line_length;int colour_fg;int colour_bg;bool flush_dcache;ushort *cmap;
};
//
struct video_uc_platdata {uint align;uint size;ulong base;
};
//display crtc控制器
struct rockchip_crtc {const struct rockchip_crtc_funcs *funcs;const void *data;struct drm_display_mode active_mode;bool hdmi_hpd : 1;bool active : 1;
};
//display的连接器
struct rockchip_connector {const struct rockchip_connector_funcs *funcs;const void *data;
};
//display 桥接状态
struct rockchip_bridge {struct udevice *dev;const struct rockchip_bridge_funcs *funcs;struct display_state *state;
};
//display  phy接口
struct rockchip_phy {struct udevice *dev;const struct rockchip_phy_funcs *funcs;const void *data;int soc_type;
};
//display  phy数据
struct public_phy_data {const struct rockchip_phy *phy_drv;int phy_node;int public_phy_type;bool phy_init;
};
//uboot的display driver
U_BOOT_DRIVER(rockchip_display) = {.name   = "rockchip_display",.id = UCLASS_VIDEO,.of_match = rockchip_display_ids,.bind = rockchip_display_bind,.probe = rockchip_display_probe,
};
rockchip_display_probe//寻找dts的route节点,route节点下有很多子节点,子节点的接口有dsi、rgb、route_node = dev_read_subnode(dev, "route");//然后读取子节点的配置参数ofnode_for_each_subnode(node, route_node) {if (!ofnode_is_available(node))continue;//通过connct参数中寻找该节点,再找到port父节点接口phandle = ofnode_read_u32_default(node, "connect", -1);if (phandle < 0) {printf("Warn: can't find connect node's handle\n");continue;}//ep_node 是connect参数 实际申明的节点ep_node = of_find_node_by_phandle(phandle);if (!ofnode_valid(np_to_ofnode(ep_node))) {printf("Warn: can't find endpoint node from phandle\n");continue;}port_node = of_get_parent(ep_node);if (!ofnode_valid(np_to_ofnode(port_node))) {printf("Warn: can't find port node from phandle\n");continue;}port_parent_node = of_get_parent(port_node);if (!ofnode_valid(np_to_ofnode(port_parent_node))) {printf("Warn: can't find port parent node from phandle\n");continue;}is_ports_node = strstr(port_parent_node->full_name, "ports") ? 1 : 0;if (is_ports_node) {vop_node = of_get_parent(port_parent_node);if (!ofnode_valid(np_to_ofnode(vop_node))) {printf("Warn: can't find crtc node from phandle\n");continue;}} else {vop_node = port_parent_node;}//找到display crtc控制器ret = uclass_get_device_by_ofnode(UCLASS_VIDEO_CRTC,np_to_ofnode(vop_node),&crtc_dev);if (ret) {printf("Warn: can't find crtc driver %d\n", ret);continue;}crtc = (struct rockchip_crtc *)dev_get_driver_data(crtc_dev);//从ep_node的remote_point参数中得到申明节点的位置,在得到生成该节点的displayport 例如dsi 加入到display port链表中conn_dev = rockchip_of_find_connector(np_to_ofnode(ep_node));if (!conn_dev) {printf("Warn: can't find connect driver\n");continue;}conn = (const struct rockchip_connector *)dev_get_driver_data(conn_dev);//得到dsi port控制器的phy接口,dsi用的是mipi_dphyphy = rockchip_of_find_phy(conn_dev);//通过dsi节点来得到 bridge 节点  vop  vop-dsibridge = rockchip_of_find_bridge(conn_dev);if (bridge)panel = rockchip_of_find_panel(bridge->dev);elsepanel = rockchip_of_find_panel(conn_dev);s = malloc(sizeof(*s));if (!s)continue;memset(s, 0, sizeof(*s));//从dts 文件中读取logo,mode的参数INIT_LIST_HEAD(&s->head);ret = ofnode_read_string_index(node, "logo,mode", 0, &name);if (!strcmp(name, "fullscreen"))s->logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;elses->logo_mode = ROCKCHIP_DISPLAY_CENTER;ret = ofnode_read_string_index(node, "charge_logo,mode", 0, &name);if (!strcmp(name, "fullscreen"))s->charge_logo_mode = ROCKCHIP_DISPLAY_FULLSCREEN;elses->charge_logo_mode = ROCKCHIP_DISPLAY_CENTER;//填充rockchip_state的参数 s->blob = blob;s->panel_state.panel = panel;s->conn_state.node = conn_dev->node;s->conn_state.dev = conn_dev;s->conn_state.connector = conn;s->conn_state.phy = phy;s->conn_state.bridge = bridge;s->conn_state.overscan.left_margin = 100;s->conn_state.overscan.right_margin = 100;s->conn_state.overscan.top_margin = 100;s->conn_state.overscan.bottom_margin = 100;s->crtc_state.node = np_to_ofnode(vop_node);s->crtc_state.dev = crtc_dev;s->crtc_state.crtc = crtc;s->crtc_state.crtc_id = get_crtc_id(np_to_ofnode(ep_node));s->node = node;if (bridge)bridge->state = s;if (panel)panel->state = s;get_crtc_mcu_mode(&s->crtc_state);ret = ofnode_read_u32_default(s->crtc_state.node,"rockchip,dual-channel-swap", 0);s->crtc_state.dual_channel_swap = ret;if (connector_panel_init(s)) {printf("Warn: Failed to init panel drivers\n");free(s);continue;}if (connector_phy_init(s, data)) {printf("Warn: Failed to init phy drivers\n");free(s);continue;}list_add_tail(&s->head, &rockchip_display_list);}
//驱动程序中会遍历route节点下的子节点的connect参数,然后再通过of_find_node_by_phandle函数得到ep_node(vop_out_dsi)的定义点 通过两次调用of_get_parent函数得到该节点的父节点vop,再把vop的节点加入到crtc控制节点的链表中,通过rockchip_of_find_connector函数获取ep_node(vop_out_dsi)的节点下的remote-endpoint的参数,然后通过ofnode_get_by_phandle函数得到remote-endpoint参数(dsi_in_vop)的定义节点,然后通过三次调用ofnode_get_parent函数得到(dsi_in_vop)的父节点dsi display_port节点,加入到display_port链表中。通过调用rockchip_of_find_phy函数得到 dsi display_port节点中的phy节点的参数并加入到链表中调用rockchip_of_find_bridge函数遍历 dsi节点下的 ports节点的reg和port节点参数,再遍历port节点下的remote-endpoint的参数,调用of_get_parent三次是否可以得到父节点如果可以加入bridge链表,然后通过bridge得到panel.
//总结来说有bridge  crtc  --  encoder -- bridge --connect -- panel
//没有bridge  crtc  --  encoder --connect -- paneldisplay_subsystem: display-subsystem {compatible = "rockchip,display-subsystem";ports = <&vop_out>;status = "disabled";logo-memory-region = <&drm_logo>;route {route_dsi: route-dsi {status = "disabled";logo,uboot_1024X600 = "logo_1024X600.bmp";logo,kernel_1024X600 = "logo_kernel_1024X600.bmp";logo,uboot_480X854 = "logo_480X854.bmp";logo,kernel_480X854 = "logo_kernel_480X854.bmp";logo,uboot_480X800 = "logo_480X800.bmp";logo,kernel_480X800 = "logo_kernel_480X800.bmp";logo,uboot_800X1280 = "logo_800X1280.bmp";logo,kernel_800X1280 = "logo_kernel_800X1280.bmp";logo,mode = "center";charge_logo,mode = "center";connect = <&vop_out_dsi>;};route_rgb: route-rgb {status = "disabled";logo,uboot = "logo.bmp";logo,kernel = "logo_kernel.bmp";logo,mode = "center";charge_logo,mode = "center";connect = <&vop_out_rgb>;};};};vop: vop@ffb00000 {compatible = "rockchip,rv1126-vop";reg = <0xffb00000 0x200>, <0xffb00a00 0x400>;reg-names = "regs", "gamma_lut";rockchip,grf = <&grf>;interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;clocks = <&cru ACLK_VOP>, <&cru DCLK_VOP>, <&cru HCLK_VOP>;clock-names = "aclk_vop", "dclk_vop", "hclk_vop";iommus = <&vop_mmu>;power-domains = <&power RV1126_PD_VO>;status = "disabled";vop_out: port {#address-cells = <1>;#size-cells = <0>;vop_out_rgb: endpoint@0 {reg = <0>;remote-endpoint = <&rgb_in_vop>;};vop_out_dsi: endpoint@1 {reg = <1>;remote-endpoint = <&dsi_in_vop>;};};};dsi: dsi@ffb30000 {compatible = "rockchip,rv1126-mipi-dsi";reg = <0xffb30000 0x500>;interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;clocks = <&cru PCLK_DSIHOST>, <&mipi_dphy>;clock-names = "pclk", "hs_clk";resets = <&cru SRST_DSIHOST_P>;reset-names = "apb";phys = <&mipi_dphy>;phy-names = "mipi_dphy";rockchip,grf = <&grf>;#address-cells = <1>;#size-cells = <0>;power-domains = <&power RV1126_PD_VO>;status = "disabled";ports {port {dsi_in_vop: endpoint {remote-endpoint = <&vop_out_dsi>;};};};};

display_init

分别获取connect、panel、crtc的结构体信息,然后初始化

//判断通路以及控制器是否初始化过if (state->is_init)return 0;if (!conn_funcs || !crtc_funcs) {printf("failed to find connector or crtc functions\n");return -ENXIO;}if (crtc_state->crtc->active &&memcmp(&crtc_state->crtc->active_mode, &conn_state->screen[lcd_index].mode,sizeof(struct drm_display_mode))) {printf("%s has been used for output type: %d, mode: %dx%dp%d\n",crtc_state->dev->name,crtc_state->crtc->active_mode.type,crtc_state->crtc->active_mode.hdisplay,crtc_state->crtc->active_mode.vdisplay,crtc_state->crtc->active_mode.vrefresh);return -ENODEV;}
//设置crtc控制器最大分辨率
if (crtc_funcs->preinit) {ret = crtc_funcs->preinit(state);if (ret)return ret;}
//panel初始化,设置bus_format -> 100e
if (panel_state->panel)rockchip_panel_init(panel_state->panel);
//connect初始化
if (conn_funcs->init) {ret = conn_funcs->init(state);if (ret)goto deinit;
}
//crtc和conect的prepare
if (crtc_funcs->prepare)crtc_funcs->prepare(state);if (conn_funcs->prepare)conn_funcs->prepare(state, -1);
//panel的类型获取比如使用什么屏
if (panel_state->panel)display_get_lcd_index(panel_state->panel);
//panel的timing 和其他参数
if (panel_state->panel) {ret = display_get_timing(state);mode = &conn_state->screen[lcd_index].mode;if (!ret)conn_state->bpc = panel_state->panel->bpc;#if defined(CONFIG_I2C_EDID)if (ret < 0 && conn_funcs->get_edid) {rockchip_panel_prepare(panel_state->panel);ret = conn_funcs->get_edid(state);if (!ret) {ret = edid_get_drm_mode((void *)&conn_state->edid,sizeof(conn_state->edid),mode, &bpc);if (!ret) {conn_state->bpc = bpc;edid_print_info((void *)&conn_state->edid);}}}#endif
} else if (conn_state->bridge) {ret = video_bridge_read_edid(conn_state->bridge->dev,conn_state->edid, EDID_SIZE);if (ret > 0) {#if defined(CONFIG_I2C_EDID)ret = edid_get_drm_mode(conn_state->edid, ret, mode,&bpc);if (!ret) {conn_state->bpc = bpc;edid_print_info((void *)&conn_state->edid);}#endif} else {ret = video_bridge_get_timing(conn_state->bridge->dev);}
} else if (conn_funcs->get_timing) {ret = conn_funcs->get_timing(state);
} else if (conn_funcs->get_edid) {ret = conn_funcs->get_edid(state);#if defined(CONFIG_I2C_EDID)if (!ret) {ret = edid_get_drm_mode((void *)&conn_state->edid,sizeof(conn_state->edid), mode,&bpc);if (!ret) {conn_state->bpc = bpc;edid_print_info((void *)&conn_state->edid);}}
#endif}//获取display的时序和前后栏参数
static int display_get_timing(struct display_state *state)
{struct connector_state *conn_state = &state->conn_state;//struct drm_display_mode *mode = &conn_state->mode;//struct mipi_screen *mscreen = conn_state->screen;const struct drm_display_mode *m;struct panel_state *panel_state = &state->panel_state;const struct rockchip_panel *panel = panel_state->panel;if (dev_of_valid(panel->dev) &&!display_get_timing_from_dts(panel_state, conn_state)) {printf("Using display timing dts %d\n", conn_state->screen[lcd_index].mode.hdisplay);return 0;}if (panel->data) {m = (const struct drm_display_mode *)panel->data;memcpy(&conn_state->screen[lcd_index].mode, m, sizeof(*m));printf("Using display timing from compatible panel driver\n");return 0;}return -ENODEV;
}
//具体参数从dts中获取,首先获取到mipilcd参数节点,再得到lcd的子节点有几个,然后遍历子节点把dts的参数赋值到具体的panel上
static int display_get_timing_from_dts(struct panel_state *panel_state,struct connector_state *conn_state)
{struct rockchip_panel *panel = panel_state->panel;int phandle;int hactive, vactive, pixelclock;int hfront_porch, hback_porch, hsync_len;int vfront_porch, vback_porch, vsync_len;int val, flags = 0;ofnode timing, native_mode;const char *lcd_name;int len = 0;int index = -1;int lcd_phandle;ofnode lcd_list;ofnode lcd_node;struct mipi_screen *mscreen;int i = 0, j = 0;lcd_phandle = dev_read_u32_default(panel->dev, "mipilcd", -1);lcd_list = np_to_ofnode(of_find_node_by_phandle(lcd_phandle));if (!ofnode_valid(lcd_list)) {printf("failed to get display timings from DT\n");return -ENXIO;}ofnode_for_each_subnode(lcd_node, lcd_list) {lcd_name = ofnode_get_property(lcd_node, "name", &len);if(0 == strncmp(lcd_name, "lcd", 3)) {index = atoi((lcd_name+3));if(index == 0) {continue;}i++;}}mscreen = calloc(i+1, sizeof(struct mipi_screen));if (mscreen == NULL) {printf("failed to alloc mipi_screen memory\n");return -EFAULT;}ofnode_for_each_subnode(lcd_node, lcd_list) {lcd_name = ofnode_get_property(lcd_node, "name", &len);if(0 == strncmp(lcd_name, "lcd", 3)) {index = atoi((lcd_name+3));if(index == 0 || index > i) {continue;}j = index;timing = ofnode_find_subnode(lcd_node, "display-timings");if (!ofnode_valid(timing))return -ENODEV;native_mode = ofnode_find_subnode(timing, "timing");if (!ofnode_valid(native_mode)) {phandle = ofnode_read_u32_default(timing, "native-mode", -1);native_mode = np_to_ofnode(of_find_node_by_phandle(phandle));if (!ofnode_valid(native_mode)) {printf("failed to get display timings from DT\n");return -ENXIO;}}FDT_GET_INT(hactive, "hactive");FDT_GET_INT(vactive, "vactive");FDT_GET_INT(pixelclock, "clock-frequency");FDT_GET_INT(hsync_len, "hsync-len");FDT_GET_INT(hfront_porch, "hfront-porch");FDT_GET_INT(hback_porch, "hback-porch");FDT_GET_INT(vsync_len, "vsync-len");FDT_GET_INT(vfront_porch, "vfront-porch");FDT_GET_INT(vback_porch, "vback-porch");FDT_GET_INT(val, "hsync-active");flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;FDT_GET_INT(val, "vsync-active");flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;FDT_GET_INT(val, "pixelclk-active");flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;FDT_GET_INT_DEFAULT(val, "screen-rotate", 0);if (val == DRM_MODE_FLAG_XMIRROR) {flags |= DRM_MODE_FLAG_XMIRROR;} else if (val == DRM_MODE_FLAG_YMIRROR) {flags |= DRM_MODE_FLAG_YMIRROR;} else if (val == DRM_MODE_FLAG_XYMIRROR) {flags |= DRM_MODE_FLAG_XMIRROR;flags |= DRM_MODE_FLAG_YMIRROR;}mscreen[j].mode.hdisplay = hactive;mscreen[j].mode.hsync_start = mscreen[j].mode.hdisplay + hfront_porch;mscreen[j].mode.hsync_end = mscreen[j].mode.hsync_start + hsync_len;mscreen[j].mode.htotal = mscreen[j].mode.hsync_end + hback_porch;mscreen[j].mode.vdisplay = vactive;mscreen[j].mode.vsync_start = mscreen[j].mode.vdisplay + vfront_porch;mscreen[j].mode.vsync_end = mscreen[j].mode.vsync_start + vsync_len;mscreen[j].mode.vtotal = mscreen[j].mode.vsync_end + vback_porch;mscreen[j].mode.clock = pixelclock / 1000;mscreen[j].mode.flags = flags;}}conn_state->screen = mscreen;return 0;
}

display logo

//首先调用display_init 初始化display的crtc connect 和pannel
ret = display_init(state);
if (!state->is_init || ret)
return -ENODEV;
//加载logo
if (load_bmp_logo(&state->logo, state->ulogo_name))printf("failed to display uboot logo\n");
//设定logo 显示模式 全屏或者居中if (logo->mode == ROCKCHIP_DISPLAY_FULLSCREEN) {crtc_state->crtc_x = 0;crtc_state->crtc_y = 0;crtc_state->crtc_w = hdisplay;crtc_state->crtc_h = vdisplay;} else {if (crtc_state->src_w >= hdisplay) {crtc_state->crtc_x = 0;crtc_state->crtc_w = hdisplay;} else {crtc_state->crtc_x = (hdisplay - crtc_state->src_w) / 2;crtc_state->crtc_w = crtc_state->src_w;}if (crtc_state->src_h >= vdisplay) {crtc_state->crtc_y = 0;crtc_state->crtc_h = vdisplay;} else {crtc_state->crtc_y = (vdisplay - crtc_state->src_h) / 2;crtc_state->crtc_h = crtc_state->src_h;}}
//调用ctrc的plane 设定display_set_plane(state);display_enable(state);
//conn_funcs->prepare 下发panel 参数
static int display_enable(struct display_state *state)
{struct connector_state *conn_state = &state->conn_state;const struct rockchip_connector *conn = conn_state->connector;const struct rockchip_connector_funcs *conn_funcs = conn->funcs;struct crtc_state *crtc_state = &state->crtc_state;const struct rockchip_crtc *crtc = crtc_state->crtc;const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;struct panel_state *panel_state = &state->panel_state;if (!state->is_init)return -EINVAL;if (state->is_enable)return 0;if (crtc_funcs->prepare)crtc_funcs->prepare(state);if (conn_funcs->prepare)conn_funcs->prepare(state, 0);if (conn_state->bridge)rockchip_bridge_pre_enable(conn_state->bridge);if (panel_state->panel)rockchip_panel_prepare(panel_state->panel);if (crtc_funcs->enable)crtc_funcs->enable(state);if (conn_funcs->enable)conn_funcs->enable(state);if (conn_state->bridge)rockchip_bridge_enable(conn_state->bridge);if (panel_state->panel)rockchip_panel_enable(panel_state->panel);state->is_enable = true;return 0;
}

uboot drm框架相关推荐

  1. Android DRM框架分析

    Android DRM框架分析 1. DRM框架 2.DRM架构 3.DRM插件 4. 实现 5.DRM插件详情 6.MediaDrm 7.MediaCrypto 8.参考链接 1. DRM框架 An ...

  2. DRM框架(vkms)分析(9)----drm驱动创建fbdevice分析(以rockchip_drm_drv为例)

    本文主要介绍DRM框架里的fbdev兼容逻辑 一 framebuffer框架简单介绍 framebuffer框架下fbdev的注册主要三步步: (1)创建fbdev操作函数,以rockchip为例: ...

  3. Android DRM框架与基础知识

    Android DRM框架与基础知识 Android DRM框架 DRM框架的目的:能让安卓设备可以播放更多的内容,不同的内容和硬件设备可能使用的是不同的内容版权保护机制或者没有版权管理机制,但是安卓 ...

  4. Linux内核4.14版本——drm框架分析(1)——drm简介

    目录 1. DRM简介(Direct Rendering Manager) 1.1 DRM发展历史 1.2 DRM架构对比FB架构优势 1.3 DRM图形显示框架 1.4 DRM图形显示框架涉及元素 ...

  5. Linux图形显示DRM框架学习

    一.Direct Rendering Manager(DRM)是linux内核子系统,负责与显卡交互.DRM提供一组API,用户空间程序可以使用该API将命令和数据发送到GPU或者专用图形处理硬件(如 ...

  6. 3588 Rockchip_基于 DRM 框架的 HDMI 开发指南

    ROCKCHIP_基于 DRM 框架的 HDMI 开发指南-1 1 简介 OVERVIEW-1 2 变量定义 VARIABLE DEFINITION -1 3 HDMI/DP 相关配置 HDMI/DP ...

  7. uboot构建框架6-u-boot.bin生成过程追踪

    先看终极目标 在配置完毕的情况下,我们在uboot根目录敲下"make"命令,就会执行一系列动作,产生一系列结果.这结果之一,便是u-boot.bin.这个u-boot.bin是一 ...

  8. DRM框架(vkms)分析(6)---- plane初始化

    一 drm_plane结构体 struct drm_plane {struct drm_device *dev;//挂载到&drm_mode_config.plane_liststruct l ...

  9. linux drm 内存管理,Linux RK3399 DRM 框架及代码流程 · Younix’s Studio

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? RK3399 OS: Android 6.0 Kernel: 4.4 Version: v2017.04 DRM 简介 ...

最新文章

  1. 14.8类成员的属性
  2. WinForm编程数据视图之DataGridView浅析(续)
  3. python爬取素材图片代码_基于Python爬取素材网站音频文件
  4. php redis 投票_高性能Redis服务架构分析与搭建
  5. Visual Studio Developer Assistant 3月新功能展示
  6. java周边技术文摘
  7. Akka的Actor生命周期《Eight》译
  8. java 百度地图返回坐标_Java使用百度地图API,根据地址,查询地址坐标。
  9. 译:在C#中使用LINQ To SQL
  10. 中国射频前端产业现状分析
  11. android webview 加载内容,Android中通过Java获取Webview加载内容
  12. 生物统计学(biostatistics)学习笔记(三)
  13. matlab如何插入“埃”这个符号
  14. 如何成为一个游戏制作人——教程企划
  15. Why Would I Ever
  16. 暗影精灵7安装Ubuntu双系统、RTX3060 Nvidia 驱动及搭建深度学习环境
  17. 神秘贼掉包二维码,支付宝赔偿200多,烧烤小哥为何还骂支付宝没良心?
  18. 解决管理问题的基本思维方式
  19. php广告管理,DedeCMS的广告管理功能
  20. JS实现视频弹幕效果

热门文章

  1. 获取保存在路由器中的ADSL账号和密码
  2. 35、ubuntu20.04搭建瑞芯微的npu仿真环境和测试rv1126的Debain系统下的yolov5+npu检测功能以及RKNN推理部署以及RTSP视频流解码
  3. 深圳两青年在伊拉克炮火中淘金400万
  4. 吊炸天的云原生,到底是个啥
  5. 中国资源卫星应用中心_数据下载
  6. 我的世界服务器修改个人游戏模式吗,我的世界1period;12指令更改模式 | 手游网游页游攻略大全...
  7. HJ87 密码强度等级(一把过)
  8. 性价比哪家强?富勒G93S光磁微动鼠标深度评测
  9. 2020-04-03
  10. 2021年最新Android面试点梳理,成功入职腾讯