static const struct drm_crtc_helper_funcs sprd_crtc_helper_funcs = {
.mode_set_nofb = sprd_crtc_mode_set_nofb,
.mode_valid = sprd_crtc_mode_valid,
.atomic_check = sprd_crtc_atomic_check, //检查显示的参数
.atomic_begin = sprd_crtc_atomic_begin, //在一帧显示开始前做的处理
.atomic_flush = sprd_crtc_atomic_flush, //提交硬件显示
.atomic_enable = sprd_crtc_atomic_enable,
.atomic_disable = sprd_crtc_atomic_disable,
};
static const struct drm_crtc_funcs sprd_crtc_funcs = {
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,//framebuffer里的帧不会被修改而产生窜帧的情况, 当page_flip完成后,会通过event通知用户层准备好下一帧的数据;
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.enable_vblank = sprd_crtc_enable_vblank,
.disable_vblank = sprd_crtc_disable_vblank,
};
static const struct drm_plane_helper_funcs sprd_plane_helper_funcs = {
.prepare_fb = sprd_plane_prepare_fb, //预先对图层进行处理
.cleanup_fb = sprd_plane_cleanup_fb, //图层显示完成后的处理
.atomic_check = sprd_plane_atomic_check, //在显示前进行参数检查
.atomic_update = sprd_plane_atomic_update, //更新图层参数
.atomic_disable = sprd_plane_atomic_disable, //关闭图层
};
static const struct drm_plane_funcs sprd_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
.reset = sprd_plane_reset,
.atomic_duplicate_state = sprd_plane_atomic_duplicate_state,
.atomic_destroy_state = sprd_plane_atomic_destroy_state,
.atomic_set_property = sprd_plane_atomic_set_property,
.atomic_get_property = sprd_plane_atomic_get_property,
};
//ENCODER/helper funcs
static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
.atomic_check = dsi_encoder_atomic_check,
.mode_valid = dsi_encoder_mode_valid,
.mode_set = dsi_encoder_mode_set,
.enable = dsi_encoder_enable,
.disable = dsi_encoder_disable
};
static const struct drm_encoder_funcs dw_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
//CONNECTOR/helper funcs
static const struct drm_connector_helper_funcs
panel_bridge_connector_helper_funcs = {
.get_modes = panel_bridge_connector_get_modes,
};
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,
};
DIS 需要实现的函数
static struct dsi_core_ops dwc_mipi_dsi_host_ops = {
.check_version = dsi_check_version,
.power_en = dsi_power_enable,
.video_mode = dsi_video_mode,
.cmd_mode = dsi_cmd_mode,
.is_cmd_mode = dsi_is_cmd_mode,
.rx_vcid = dsi_rx_vcid,
.video_vcid = dsi_video_vcid,
.dpi_video_burst_mode = dsi_dpi_video_burst_mode,
.dpi_color_coding = dsi_dpi_color_coding,
.dpi_18_loosely_packet_en = dsi_dpi_18_loosely_packet_en,
.dpi_color_mode_pol = dsi_dpi_color_mode_pol,
.dpi_shut_down_pol = dsi_dpi_shut_down_pol,
.dpi_hsync_pol = dsi_dpi_hsync_pol,
.dpi_vsync_pol = dsi_dpi_vsync_pol,
.dpi_data_en_pol = dsi_dpi_data_en_pol,
.dpi_hline_time = dsi_dpi_hline_time,
.dpi_hsync_time = dsi_dpi_hsync_time,
.dpi_hbp_time = dsi_dpi_hbp_time,
.dpi_vact = dsi_dpi_vact,
.dpi_vfp = dsi_dpi_vfp,
.dpi_vbp = dsi_dpi_vbp,
.dpi_vsync = dsi_dpi_vsync,
.dpi_hporch_lp_en = dsi_dpi_hporch_lp_en,
.dpi_vporch_lp_en = dsi_dpi_vporch_lp_en,
.dpi_frame_ack_en = dsi_dpi_frame_ack_en,
.dpi_chunk_num = dsi_dpi_chunk_num,
.dpi_null_packet_size = dsi_dpi_null_packet_size,
.dpi_video_packet_size = dsi_dpi_video_packet_size,
.edpi_max_pkt_size = dsi_edpi_max_pkt_size,
.tear_effect_ack_en = dsi_tear_effect_ack_en,
.cmd_ack_request_en = dsi_cmd_ack_request_en,
.cmd_mode_lp_cmd_en = dsi_cmd_mode_lp_cmd_en,
.video_mode_lp_cmd_en = dsi_video_mode_lp_cmd_en,
.set_packet_header = dsi_set_packet_header,
.set_packet_payload = dsi_set_packet_payload,
.get_rx_payload = dsi_get_rx_payload,
.bta_en = dsi_bta_en,
.eotp_rx_en = dsi_eotp_rx_en,
.eotp_tx_en = dsi_eotp_tx_en,
.ecc_rx_en = dsi_ecc_rx_en,
.crc_rx_en = dsi_crc_rx_en,
.is_bta_returned = dsi_is_bta_returned,
.is_rx_payload_fifo_full = dsi_is_rx_payload_fifo_full,
.is_rx_payload_fifo_empty = dsi_is_rx_payload_fifo_empty,
.is_tx_payload_fifo_full = dsi_is_tx_payload_fifo_full,
.is_tx_payload_fifo_empty = dsi_is_tx_payload_fifo_empty,
.is_tx_cmd_fifo_full = dsi_is_tx_cmd_fifo_full,
.is_tx_cmd_fifo_empty = dsi_is_tx_cmd_fifo_empty,
.datalane_hs2lp_config = dsi_datalane_hs2lp_config,
.datalane_lp2hs_config = dsi_datalane_lp2hs_config,
.clklane_hs2lp_config = dsi_clklane_hs2lp_config,
.clklane_lp2hs_config = dsi_clklane_lp2hs_config,
.max_read_time = dsi_max_read_time,
.nc_clk_en = dsi_nc_clk_en,
.tx_escape_division = dsi_tx_escape_division,
.timeout_clock_division = dsi_timeout_clock_division,
.lp_rx_timeout = dsi_lp_rx_timeout,
.hs_tx_timeout = dsi_hs_tx_timeout,
.bta_presp_timeout = dsi_bta_presp_timeout,
.lp_write_presp_timeout = dsi_lp_write_presp_timeout,
.lp_read_presp_timeout = dsi_lp_read_presp_timeout,
.hs_write_presp_timeout = dsi_hs_write_presp_timeout,
.hs_read_presp_timeout = dsi_hs_read_presp_timeout,
.int0_status = dsi_int0_status,
.int1_status = dsi_int1_status,
.int0_mask = dsi_int0_mask,
.int1_mask = dsi_int1_mask,
};
例如版本判断
static bool dsi_check_version(struct dsi_context *ctx)
{
struct dsi_reg *reg = (struct dsi_reg *)ctx->base;
/* DWC_mipi_dsi_host_1.31a */
if (read32(®->VERSION) == 0x3133312a)
return true;
/* DWC_mipi_dsi_host_1.21a */
if (read32(®->VERSION) == 0x3132302a)
return true;
return false;
}
DPU部分
static struct dpu_core_ops dpu_r3p0_ops = {
.parse_dt = dpu_parse_dt,
.version = dpu_get_version,
.init = dpu_init,
.uninit = dpu_uninit,
.run = dpu_run,
.stop = dpu_stop,
.isr = dpu_isr,
.ifconfig = dpu_dpi_init,
.capability = dpu_capability,
.flip = dpu_flip,
.bg_color = dpu_bgcolor,
.enable_vsync = enable_vsync,
.disable_vsync = disable_vsync,
.enhance_set = dpu_enhance_set,
.enhance_get = dpu_enhance_get,
.modeset = dpu_modeset,
.write_back = dpu_write_back,
};
cmd模式 和 video模式设置
static int sprd_dsi_resume(struct sprd_dsi *dsi)
{
if (dsi->glb && dsi->glb->power)
dsi->glb->power(&dsi->ctx, true);
if (dsi->glb && dsi->glb->enable)
dsi->glb->enable(&dsi->ctx);
if (dsi->glb && dsi->glb->reset)
dsi->glb->reset(&dsi->ctx);
sprd_dsi_init(dsi);
if (dsi->ctx.work_mode == DSI_MODE_VIDEO)
sprd_dsi_dpi_video(dsi);
else
sprd_dsi_edpi_video(dsi);
DRM_INFO("dsi resume OK\n");
return 0;
}
```c
static void sprd_dsi_encoder_enable(struct drm_encoder *encoder)
{
struct sprd_dsi *dsi = encoder_to_dsi(encoder);
struct sprd_dpu *dpu = crtc_to_dpu(encoder->crtc);
static bool is_enabled = true;
DRM_INFO("%s()\n", __func__);
mutex_lock(&dsi_lock);
/* add if condition to avoid resume dsi for SR feature.
* if esd recovery happened during display suspend, skip dsi resume.
*/
if (!encoder->crtc || !encoder->crtc->state->active ||
(encoder->crtc->state->mode_changed &&
!encoder->crtc->state->active_changed)) {
DRM_INFO("skip dsi resume\n");
mutex_unlock(&dsi_lock);
return;
}
if (dsi->ctx.is_inited) {
mutex_unlock(&dsi_lock);
DRM_ERROR("dsi is inited\n");
return;
}
if (is_enabled) {
is_enabled = false;
dsi->ctx.is_inited = true;
mutex_unlock(&dsi_lock);
return;
}
pm_runtime_get_sync(dsi->dev.parent);
sprd_dsi_resume(dsi);
sprd_dphy_resume(dsi->phy);
sprd_dsi_lp_cmd_enable(dsi, true);
。。。。
static const struct drm_encoder_helper_funcs sprd_encoder_helper_funcs = {
.atomic_check = sprd_dsi_encoder_atomic_check,
.mode_set = sprd_dsi_encoder_mode_set,
.enable = sprd_dsi_encoder_enable,
.disable = sprd_dsi_encoder_disable
};