2929#define DISP_REG_OVL_DATAPATH_CON 0x0024
3030#define OVL_LAYER_SMI_ID_EN BIT(0)
3131#define OVL_BGCLR_SEL_IN BIT(2)
32+ #define OVL_LAYER_AFBC_EN (n ) BIT(4+n)
3233#define DISP_REG_OVL_ROI_BGCLR 0x0028
3334#define DISP_REG_OVL_SRC_CON 0x002c
3435#define DISP_REG_OVL_CON (n ) (0x0030 + 0x20 * (n))
3536#define DISP_REG_OVL_SRC_SIZE (n ) (0x0038 + 0x20 * (n))
3637#define DISP_REG_OVL_OFFSET (n ) (0x003c + 0x20 * (n))
38+ #define DISP_REG_OVL_PITCH_MSB (n ) (0x0040 + 0x20 * (n))
39+ #define OVL_PITCH_MSB_2ND_SUBBUF BIT(16)
3740#define DISP_REG_OVL_PITCH (n ) (0x0044 + 0x20 * (n))
3841#define DISP_REG_OVL_RDMA_CTRL (n ) (0x00c0 + 0x20 * (n))
3942#define DISP_REG_OVL_RDMA_GMC (n ) (0x00c8 + 0x20 * (n))
4043#define DISP_REG_OVL_ADDR_MT2701 0x0040
4144#define DISP_REG_OVL_ADDR_MT8173 0x0f40
4245#define DISP_REG_OVL_ADDR (ovl , n ) ((ovl)->data->addr + 0x20 * (n))
46+ #define DISP_REG_OVL_HDR_ADDR (ovl , n ) ((ovl)->data->addr + 0x20 * (n) + 0x04)
47+ #define DISP_REG_OVL_HDR_PITCH (ovl , n ) ((ovl)->data->addr + 0x20 * (n) + 0x08)
4348
4449#define GMC_THRESHOLD_BITS 16
4550#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
@@ -67,6 +72,7 @@ struct mtk_disp_ovl_data {
6772 unsigned int layer_nr ;
6873 bool fmt_rgb565_is_0 ;
6974 bool smi_id_en ;
75+ bool supports_afbc ;
7076};
7177
7278/*
@@ -172,7 +178,14 @@ void mtk_ovl_stop(struct device *dev)
172178 reg = reg & ~OVL_LAYER_SMI_ID_EN ;
173179 writel_relaxed (reg , ovl -> regs + DISP_REG_OVL_DATAPATH_CON );
174180 }
181+ }
175182
183+ static void mtk_ovl_set_afbc (struct mtk_disp_ovl * ovl , struct cmdq_pkt * cmdq_pkt ,
184+ int idx , bool enabled )
185+ {
186+ mtk_ddp_write_mask (cmdq_pkt , enabled ? OVL_LAYER_AFBC_EN (idx ) : 0 ,
187+ & ovl -> cmdq_reg , ovl -> regs ,
188+ DISP_REG_OVL_DATAPATH_CON , OVL_LAYER_AFBC_EN (idx ));
176189}
177190
178191void mtk_ovl_config (struct device * dev , unsigned int w ,
@@ -310,11 +323,23 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
310323 struct mtk_disp_ovl * ovl = dev_get_drvdata (dev );
311324 struct mtk_plane_pending_state * pending = & state -> pending ;
312325 unsigned int addr = pending -> addr ;
313- unsigned int pitch = pending -> pitch & 0xffff ;
326+ unsigned int hdr_addr = pending -> hdr_addr ;
327+ unsigned int pitch = pending -> pitch ;
328+ unsigned int hdr_pitch = pending -> hdr_pitch ;
314329 unsigned int fmt = pending -> format ;
315330 unsigned int offset = (pending -> y << 16 ) | pending -> x ;
316331 unsigned int src_size = (pending -> height << 16 ) | pending -> width ;
317332 unsigned int con ;
333+ bool is_afbc = pending -> modifier != DRM_FORMAT_MOD_LINEAR ;
334+ union overlay_pitch {
335+ struct split_pitch {
336+ u16 lsb ;
337+ u16 msb ;
338+ } split_pitch ;
339+ u32 pitch ;
340+ } overlay_pitch ;
341+
342+ overlay_pitch .pitch = pitch ;
318343
319344 if (!pending -> enable ) {
320345 mtk_ovl_layer_off (dev , idx , cmdq_pkt );
@@ -335,9 +360,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
335360 addr += pending -> pitch - 1 ;
336361 }
337362
363+ if (ovl -> data -> supports_afbc )
364+ mtk_ovl_set_afbc (ovl , cmdq_pkt , idx , is_afbc );
365+
338366 mtk_ddp_write_relaxed (cmdq_pkt , con , & ovl -> cmdq_reg , ovl -> regs ,
339367 DISP_REG_OVL_CON (idx ));
340- mtk_ddp_write_relaxed (cmdq_pkt , pitch , & ovl -> cmdq_reg , ovl -> regs ,
368+ mtk_ddp_write_relaxed (cmdq_pkt , overlay_pitch . split_pitch . lsb , & ovl -> cmdq_reg , ovl -> regs ,
341369 DISP_REG_OVL_PITCH (idx ));
342370 mtk_ddp_write_relaxed (cmdq_pkt , src_size , & ovl -> cmdq_reg , ovl -> regs ,
343371 DISP_REG_OVL_SRC_SIZE (idx ));
@@ -346,6 +374,20 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
346374 mtk_ddp_write_relaxed (cmdq_pkt , addr , & ovl -> cmdq_reg , ovl -> regs ,
347375 DISP_REG_OVL_ADDR (ovl , idx ));
348376
377+ if (is_afbc ) {
378+ mtk_ddp_write_relaxed (cmdq_pkt , hdr_addr , & ovl -> cmdq_reg , ovl -> regs ,
379+ DISP_REG_OVL_HDR_ADDR (ovl , idx ));
380+ mtk_ddp_write_relaxed (cmdq_pkt ,
381+ OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch .split_pitch .msb ,
382+ & ovl -> cmdq_reg , ovl -> regs , DISP_REG_OVL_PITCH_MSB (idx ));
383+ mtk_ddp_write_relaxed (cmdq_pkt , hdr_pitch , & ovl -> cmdq_reg , ovl -> regs ,
384+ DISP_REG_OVL_HDR_PITCH (ovl , idx ));
385+ } else {
386+ mtk_ddp_write_relaxed (cmdq_pkt ,
387+ overlay_pitch .split_pitch .msb ,
388+ & ovl -> cmdq_reg , ovl -> regs , DISP_REG_OVL_PITCH_MSB (idx ));
389+ }
390+
349391 mtk_ovl_layer_on (dev , idx , cmdq_pkt );
350392}
351393
@@ -492,6 +534,15 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
492534 .smi_id_en = true,
493535};
494536
537+ static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
538+ .addr = DISP_REG_OVL_ADDR_MT8173 ,
539+ .gmc_bits = 10 ,
540+ .layer_nr = 4 ,
541+ .fmt_rgb565_is_0 = true,
542+ .smi_id_en = true,
543+ .supports_afbc = true,
544+ };
545+
495546static const struct of_device_id mtk_disp_ovl_driver_dt_match [] = {
496547 { .compatible = "mediatek,mt2701-disp-ovl" ,
497548 .data = & mt2701_ovl_driver_data },
@@ -505,6 +556,8 @@ static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
505556 .data = & mt8192_ovl_driver_data },
506557 { .compatible = "mediatek,mt8192-disp-ovl-2l" ,
507558 .data = & mt8192_ovl_2l_driver_data },
559+ { .compatible = "mediatek,mt8195-disp-ovl" ,
560+ .data = & mt8195_ovl_driver_data },
508561 {},
509562};
510563MODULE_DEVICE_TABLE (of , mtk_disp_ovl_driver_dt_match );
0 commit comments