内容和参考

内容

参考

硬件信息

image.png

软件代码

设备树配置

参考文档:Documentation/devicetree/bindings/display/arm,malidp.txt

编译选项

  1. mali-dp-y := malidp_drv.o malidp_hw.o malidp_planes.o malidp_crtc.o
  2. mali-dp-y += malidp_mw.o

代码流程

malidp初始化流程

mali-dp550驱动-1 - 图2

硬件描述信息

mali-dp得硬件描述不仅仅来源于设备树,驱动中患有一个表位于 struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] 中,描述了寄存器及硬件得详细信息。

static const struct of_device_id  malidp_drm_of_match[] = {
    { .compatible = "arm,mali-dp550", .data = &malidp_device[MALIDP_550]},
}
[MALIDP_550] = {
    .map = {
        .coeffs_base = MALIDP550_COEFFS_BASE,
        .se_base = MALIDP550_SE_BASE,
        .dc_base = MALIDP550_DC_BASE,
        .out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
        .features = MALIDP_REGMAP_HAS_CLEARIRQ |
            MALIDP_DEVICE_AFBC_SUPPORT_SPLIT |
            MALIDP_DEVICE_AFBC_YUV_420_10_SUPPORT_SPLIT |
            MALIDP_DEVICE_AFBC_YUYV_USE_422_P2,
        .n_layers = ARRAY_SIZE(malidp550_layers),
        .layers = malidp550_layers,
        .de_irq_map = {
            ......
        .pixel_formats = malidp550_de_formats,
        .n_pixel_formats = ARRAY_SIZE(malidp550_de_formats),
        .bus_align_bytes = 8,
    },
    .query_hw = malidp550_query_hw,
    .enter_config_mode = malidp550_enter_config_mode,
    .leave_config_mode = malidp550_leave_config_mode,
    .in_config_mode = malidp550_in_config_mode,
    .set_config_valid = malidp550_set_config_valid,
    .modeset = malidp550_modeset,
    .rotmem_required = malidp550_rotmem_required,
    .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs,
    .se_calc_mclk = malidp550_se_calc_mclk,
    .enable_memwrite = malidp550_enable_memwrite,
    .disable_memwrite = malidp550_disable_memwrite,
    .features = 0,
},

// 支持得图像格式
static const struct malidp_format_id malidp550_de_formats[] = {
    MALIDP_COMMON_FORMATS,
};

// 支持得图层:4层图层,LV1, LG1, LV2, LS
static const struct malidp_layer malidp550_layers[] = {
    /* id, base address, fb pointer address base, stride offset,
     *    yuv2rgb matrix offset, mmu control register offset, rotation_features
     */
    { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
        MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
        MALIDP550_DE_LV1_AD_CTRL },
    { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
        MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY,
        MALIDP550_DE_LG_AD_CTRL },
    { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
        MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY,
        MALIDP550_DE_LV2_AD_CTRL },
    { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
        MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE, 0 },
};

malidp_de_planes_init

malidp550_layers 中可以看到 mali-dp550支持4个plane,对每层plane 从 malidp550_de_formats 中 获取到当前层所支持得formats,然后依次调用以下进行初始化: mali-dp550驱动-1 - 图3

中断相关

初始化 和 卸载

在手册 2.4.1 章节中 描述了:
Mali-DP550 每路支持两个中断: IRQDE, IRQSE

  • IRQDE0. Interrupt request signal from the primary display core and primary display engine.
  • IRQSE0. Interrupt request signal from the primary scaling engine.

这里配置有几个概念:

  • mali-dp550 包含IRQDE 和 IRQSE 两个中断, 其中DC得状态也在DE中断中处理。
  • mali-dp550 得 DE, DC, SE前边几个寄存器地址一致,所以 malidp_hw_disable_irq, malidp_hw_clear_irq,malidp_hw_enable_irq 等操作中断得接口封装成统一接口。

    #define MALIDP_REG_STATUS        0x00000
    #define MALIDP_REG_SETIRQ        0x00004
    #define MALIDP_REG_MASKIRQ        0x00008
    #define MALIDP_REG_CLEARIRQ        0x0000c
    
  • mali-dp550得 disable irq 是给 MALIDP_REG_MASKIRQ 写0,而不是写1(这点和其他不一致)。

  • mali-dp550得 clear irq 是给 MALIDP_REG_CLEARIRQ 写1。
  • mali-dp550得中断使能 策略 是 根据 malidp_device 这个全局结构体中配置得策略进行使能和屏蔽得。

在中断初始化时,根据 .irq_mask进行配置 使能,在中断处理函数里 判断 .vsync_irq 和 .err_mask 状态。

struct malidp_irq_map {
    u32 irq_mask;        /* mask of IRQs that can be enabled in the block */
    u32 vsync_irq;        /* IRQ bit used for signaling during VSYNC */
    u32 err_mask;        /* mask of bits that represent errors */
};

const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
            .de_irq_map = {
                .irq_mask = MALIDP_DE_IRQ_UNDERRUN |
                        MALIDP500_DE_IRQ_AXI_ERR |
                        MALIDP500_DE_IRQ_VSYNC |
                        MALIDP500_DE_IRQ_GLOBAL,
                .vsync_irq = MALIDP500_DE_IRQ_VSYNC,
                .err_mask = MALIDP_DE_IRQ_UNDERRUN |
                        MALIDP500_DE_IRQ_AXI_ERR |
                        MALIDP500_DE_IRQ_SATURATION,
            },
            .se_irq_map = {
                .irq_mask = MALIDP500_SE_IRQ_CONF_MODE |
                        MALIDP500_SE_IRQ_CONF_VALID |
                        MALIDP500_SE_IRQ_GLOBAL,
                .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID,
                .err_mask = MALIDP500_SE_IRQ_INIT_BUSY |
                        MALIDP500_SE_IRQ_AXI_ERROR |
                        MALIDP500_SE_IRQ_OVERRUN,
            },
            .dc_irq_map = {
                .irq_mask = MALIDP500_DE_IRQ_CONF_VALID,
                .vsync_irq = MALIDP500_DE_IRQ_CONF_VALID,
            },
}

软件流程: mali-dp550驱动-1 - 图4

malidp_irq_init
    malidp_de_irq_init(drm, irq_de);
        // 屏蔽中断+清中断 
        malidp_hw_disable_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
        malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, 0xffffffff);
        malidp_hw_disable_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
        malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, 0xffffffff);
        // 注册中断
        devm_request_threaded_irq(malidp_de_irq)
        // 根据 malidp_device 中对应irq_mask 打开相应中断
        malidp_hw_enable_irq(hwdev, MALIDP_DC_BLOCK,
                 hwdev->hw->map.dc_irq_map.irq_mask);
        malidp_hw_enable_irq(hwdev, MALIDP_DE_BLOCK,
                 hwdev->hw->map.de_irq_map.irq_mask);

    malidp_se_irq_init(drm, irq_se);
        // 同上

malidp_se_irq_fini
    malidp_hw_disable_irq(hwdev, MALIDP_SE_BLOCK,
                  hwdev->hw->map.se_irq_map.irq_mask);
malidp_de_irq_fini
    // 同上