1*0e177d5cSLiu Ying // SPDX-License-Identifier: GPL-2.0+ 2*0e177d5cSLiu Ying /* 3*0e177d5cSLiu Ying * Copyright 2024 NXP 4*0e177d5cSLiu Ying */ 5*0e177d5cSLiu Ying 6*0e177d5cSLiu Ying #include <linux/bitfield.h> 7*0e177d5cSLiu Ying #include <linux/bitops.h> 8*0e177d5cSLiu Ying #include <linux/bits.h> 9*0e177d5cSLiu Ying #include <linux/math.h> 10*0e177d5cSLiu Ying 11*0e177d5cSLiu Ying #include "dc-fu.h" 12*0e177d5cSLiu Ying #include "dc-pe.h" 13*0e177d5cSLiu Ying 14*0e177d5cSLiu Ying /* STATICCONTROL */ 15*0e177d5cSLiu Ying #define SHDLDREQSTICKY_MASK GENMASK(31, 24) 16*0e177d5cSLiu Ying #define SHDLDREQSTICKY(x) FIELD_PREP(SHDLDREQSTICKY_MASK, (x)) 17*0e177d5cSLiu Ying #define BASEADDRESSAUTOUPDATE_MASK GENMASK(23, 16) 18*0e177d5cSLiu Ying #define BASEADDRESSAUTOUPDATE(x) FIELD_PREP(BASEADDRESSAUTOUPDATE_MASK, (x)) 19*0e177d5cSLiu Ying 20*0e177d5cSLiu Ying /* BURSTBUFFERMANAGEMENT */ 21*0e177d5cSLiu Ying #define SETBURSTLENGTH_MASK GENMASK(12, 8) 22*0e177d5cSLiu Ying #define SETBURSTLENGTH(x) FIELD_PREP(SETBURSTLENGTH_MASK, (x)) 23*0e177d5cSLiu Ying #define SETNUMBUFFERS_MASK GENMASK(7, 0) 24*0e177d5cSLiu Ying #define SETNUMBUFFERS(x) FIELD_PREP(SETNUMBUFFERS_MASK, (x)) 25*0e177d5cSLiu Ying #define LINEMODE_MASK BIT(31) 26*0e177d5cSLiu Ying 27*0e177d5cSLiu Ying /* SOURCEBUFFERATTRIBUTES */ 28*0e177d5cSLiu Ying #define BITSPERPIXEL_MASK GENMASK(21, 16) 29*0e177d5cSLiu Ying #define BITSPERPIXEL(x) FIELD_PREP(BITSPERPIXEL_MASK, (x)) 30*0e177d5cSLiu Ying #define STRIDE_MASK GENMASK(15, 0) 31*0e177d5cSLiu Ying #define STRIDE(x) FIELD_PREP(STRIDE_MASK, (x) - 1) 32*0e177d5cSLiu Ying 33*0e177d5cSLiu Ying /* SOURCEBUFFERDIMENSION */ 34*0e177d5cSLiu Ying #define LINEWIDTH(x) FIELD_PREP(GENMASK(13, 0), (x)) 35*0e177d5cSLiu Ying #define LINECOUNT(x) FIELD_PREP(GENMASK(29, 16), (x)) 36*0e177d5cSLiu Ying 37*0e177d5cSLiu Ying /* LAYEROFFSET */ 38*0e177d5cSLiu Ying #define LAYERXOFFSET(x) FIELD_PREP(GENMASK(14, 0), (x)) 39*0e177d5cSLiu Ying #define LAYERYOFFSET(x) FIELD_PREP(GENMASK(30, 16), (x)) 40*0e177d5cSLiu Ying 41*0e177d5cSLiu Ying /* CLIPWINDOWOFFSET */ 42*0e177d5cSLiu Ying #define CLIPWINDOWXOFFSET(x) FIELD_PREP(GENMASK(14, 0), (x)) 43*0e177d5cSLiu Ying #define CLIPWINDOWYOFFSET(x) FIELD_PREP(GENMASK(30, 16), (x)) 44*0e177d5cSLiu Ying 45*0e177d5cSLiu Ying /* CLIPWINDOWDIMENSIONS */ 46*0e177d5cSLiu Ying #define CLIPWINDOWWIDTH(x) FIELD_PREP(GENMASK(13, 0), (x) - 1) 47*0e177d5cSLiu Ying #define CLIPWINDOWHEIGHT(x) FIELD_PREP(GENMASK(29, 16), (x) - 1) 48*0e177d5cSLiu Ying 49*0e177d5cSLiu Ying enum dc_linemode { 50*0e177d5cSLiu Ying /* 51*0e177d5cSLiu Ying * Mandatory setting for operation in the Display Controller. 52*0e177d5cSLiu Ying * Works also for Blit Engine with marginal performance impact. 53*0e177d5cSLiu Ying */ 54*0e177d5cSLiu Ying LINEMODE_DISPLAY = 0, 55*0e177d5cSLiu Ying }; 56*0e177d5cSLiu Ying 57*0e177d5cSLiu Ying struct dc_fu_pixel_format { 58*0e177d5cSLiu Ying u32 pixel_format; 59*0e177d5cSLiu Ying u32 bits; 60*0e177d5cSLiu Ying u32 shifts; 61*0e177d5cSLiu Ying }; 62*0e177d5cSLiu Ying 63*0e177d5cSLiu Ying static const struct dc_fu_pixel_format pixel_formats[] = { 64*0e177d5cSLiu Ying { 65*0e177d5cSLiu Ying DRM_FORMAT_XRGB8888, 66*0e177d5cSLiu Ying R_BITS(8) | G_BITS(8) | B_BITS(8) | A_BITS(0), 67*0e177d5cSLiu Ying R_SHIFT(16) | G_SHIFT(8) | B_SHIFT(0) | A_SHIFT(0), 68*0e177d5cSLiu Ying }, 69*0e177d5cSLiu Ying }; 70*0e177d5cSLiu Ying 71*0e177d5cSLiu Ying void dc_fu_get_pixel_format_bits(struct dc_fu *fu, u32 format, u32 *bits) 72*0e177d5cSLiu Ying { 73*0e177d5cSLiu Ying int i; 74*0e177d5cSLiu Ying 75*0e177d5cSLiu Ying for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) { 76*0e177d5cSLiu Ying if (pixel_formats[i].pixel_format == format) { 77*0e177d5cSLiu Ying *bits = pixel_formats[i].bits; 78*0e177d5cSLiu Ying return; 79*0e177d5cSLiu Ying } 80*0e177d5cSLiu Ying } 81*0e177d5cSLiu Ying } 82*0e177d5cSLiu Ying 83*0e177d5cSLiu Ying void 84*0e177d5cSLiu Ying dc_fu_get_pixel_format_shifts(struct dc_fu *fu, u32 format, u32 *shifts) 85*0e177d5cSLiu Ying { 86*0e177d5cSLiu Ying int i; 87*0e177d5cSLiu Ying 88*0e177d5cSLiu Ying for (i = 0; i < ARRAY_SIZE(pixel_formats); i++) { 89*0e177d5cSLiu Ying if (pixel_formats[i].pixel_format == format) { 90*0e177d5cSLiu Ying *shifts = pixel_formats[i].shifts; 91*0e177d5cSLiu Ying return; 92*0e177d5cSLiu Ying } 93*0e177d5cSLiu Ying } 94*0e177d5cSLiu Ying } 95*0e177d5cSLiu Ying 96*0e177d5cSLiu Ying static inline void dc_fu_enable_shden(struct dc_fu *fu) 97*0e177d5cSLiu Ying { 98*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDEN, SHDEN); 99*0e177d5cSLiu Ying } 100*0e177d5cSLiu Ying 101*0e177d5cSLiu Ying static inline void dc_fu_baddr_autoupdate(struct dc_fu *fu, u8 layer_mask) 102*0e177d5cSLiu Ying { 103*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, STATICCONTROL, 104*0e177d5cSLiu Ying BASEADDRESSAUTOUPDATE_MASK, 105*0e177d5cSLiu Ying BASEADDRESSAUTOUPDATE(layer_mask)); 106*0e177d5cSLiu Ying } 107*0e177d5cSLiu Ying 108*0e177d5cSLiu Ying void dc_fu_shdldreq_sticky(struct dc_fu *fu, u8 layer_mask) 109*0e177d5cSLiu Ying { 110*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, STATICCONTROL, SHDLDREQSTICKY_MASK, 111*0e177d5cSLiu Ying SHDLDREQSTICKY(layer_mask)); 112*0e177d5cSLiu Ying } 113*0e177d5cSLiu Ying 114*0e177d5cSLiu Ying static inline void dc_fu_set_linemode(struct dc_fu *fu, enum dc_linemode mode) 115*0e177d5cSLiu Ying { 116*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, LINEMODE_MASK, 117*0e177d5cSLiu Ying mode); 118*0e177d5cSLiu Ying } 119*0e177d5cSLiu Ying 120*0e177d5cSLiu Ying static inline void dc_fu_set_numbuffers(struct dc_fu *fu, unsigned int num) 121*0e177d5cSLiu Ying { 122*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, 123*0e177d5cSLiu Ying SETNUMBUFFERS_MASK, SETNUMBUFFERS(num)); 124*0e177d5cSLiu Ying } 125*0e177d5cSLiu Ying 126*0e177d5cSLiu Ying static void dc_fu_set_burstlength(struct dc_fu *fu, dma_addr_t baddr) 127*0e177d5cSLiu Ying { 128*0e177d5cSLiu Ying unsigned int burst_size, burst_length; 129*0e177d5cSLiu Ying 130*0e177d5cSLiu Ying burst_size = 1 << __ffs(baddr); 131*0e177d5cSLiu Ying burst_size = round_up(burst_size, 8); 132*0e177d5cSLiu Ying burst_size = min(burst_size, 128U); 133*0e177d5cSLiu Ying burst_length = burst_size / 8; 134*0e177d5cSLiu Ying 135*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, BURSTBUFFERMANAGEMENT, 136*0e177d5cSLiu Ying SETBURSTLENGTH_MASK, SETBURSTLENGTH(burst_length)); 137*0e177d5cSLiu Ying } 138*0e177d5cSLiu Ying 139*0e177d5cSLiu Ying static void dc_fu_set_baseaddress(struct dc_fu *fu, enum dc_fu_frac frac, 140*0e177d5cSLiu Ying dma_addr_t baddr) 141*0e177d5cSLiu Ying { 142*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_baseaddr[frac], baddr); 143*0e177d5cSLiu Ying } 144*0e177d5cSLiu Ying 145*0e177d5cSLiu Ying void dc_fu_set_src_bpp(struct dc_fu *fu, enum dc_fu_frac frac, unsigned int bpp) 146*0e177d5cSLiu Ying { 147*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac], 148*0e177d5cSLiu Ying BITSPERPIXEL_MASK, BITSPERPIXEL(bpp)); 149*0e177d5cSLiu Ying } 150*0e177d5cSLiu Ying 151*0e177d5cSLiu Ying static void dc_fu_set_src_stride(struct dc_fu *fu, enum dc_fu_frac frac, 152*0e177d5cSLiu Ying unsigned int stride) 153*0e177d5cSLiu Ying { 154*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, fu->reg_sourcebufferattributes[frac], 155*0e177d5cSLiu Ying STRIDE_MASK, STRIDE(stride)); 156*0e177d5cSLiu Ying } 157*0e177d5cSLiu Ying 158*0e177d5cSLiu Ying static void dc_fu_set_src_buf_dimensions(struct dc_fu *fu, enum dc_fu_frac frac, 159*0e177d5cSLiu Ying int w, int h) 160*0e177d5cSLiu Ying { 161*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_sourcebufferdimension[frac], 162*0e177d5cSLiu Ying LINEWIDTH(w) | LINECOUNT(h)); 163*0e177d5cSLiu Ying } 164*0e177d5cSLiu Ying 165*0e177d5cSLiu Ying static inline void dc_fu_layeroffset(struct dc_fu *fu, enum dc_fu_frac frac, 166*0e177d5cSLiu Ying unsigned int x, unsigned int y) 167*0e177d5cSLiu Ying { 168*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_layeroffset[frac], 169*0e177d5cSLiu Ying LAYERXOFFSET(x) | LAYERYOFFSET(y)); 170*0e177d5cSLiu Ying } 171*0e177d5cSLiu Ying 172*0e177d5cSLiu Ying static inline void dc_fu_clipoffset(struct dc_fu *fu, enum dc_fu_frac frac, 173*0e177d5cSLiu Ying unsigned int x, unsigned int y) 174*0e177d5cSLiu Ying { 175*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_clipwindowoffset[frac], 176*0e177d5cSLiu Ying CLIPWINDOWXOFFSET(x) | CLIPWINDOWYOFFSET(y)); 177*0e177d5cSLiu Ying } 178*0e177d5cSLiu Ying 179*0e177d5cSLiu Ying static inline void dc_fu_clipdimensions(struct dc_fu *fu, enum dc_fu_frac frac, 180*0e177d5cSLiu Ying unsigned int w, unsigned int h) 181*0e177d5cSLiu Ying { 182*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_clipwindowdimensions[frac], 183*0e177d5cSLiu Ying CLIPWINDOWWIDTH(w) | CLIPWINDOWHEIGHT(h)); 184*0e177d5cSLiu Ying } 185*0e177d5cSLiu Ying 186*0e177d5cSLiu Ying static inline void 187*0e177d5cSLiu Ying dc_fu_set_pixel_blend_mode(struct dc_fu *fu, enum dc_fu_frac frac) 188*0e177d5cSLiu Ying { 189*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_layerproperty[frac], 0); 190*0e177d5cSLiu Ying regmap_write(fu->reg_cfg, fu->reg_constantcolor[frac], 0); 191*0e177d5cSLiu Ying } 192*0e177d5cSLiu Ying 193*0e177d5cSLiu Ying static void dc_fu_enable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac) 194*0e177d5cSLiu Ying { 195*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac], 196*0e177d5cSLiu Ying SOURCEBUFFERENABLE, SOURCEBUFFERENABLE); 197*0e177d5cSLiu Ying } 198*0e177d5cSLiu Ying 199*0e177d5cSLiu Ying static void dc_fu_disable_src_buf(struct dc_fu *fu, enum dc_fu_frac frac) 200*0e177d5cSLiu Ying { 201*0e177d5cSLiu Ying regmap_write_bits(fu->reg_cfg, fu->reg_layerproperty[frac], 202*0e177d5cSLiu Ying SOURCEBUFFERENABLE, 0); 203*0e177d5cSLiu Ying 204*0e177d5cSLiu Ying if (fu->lb) { 205*0e177d5cSLiu Ying dc_lb_pec_clken(fu->lb, CLKEN_DISABLE); 206*0e177d5cSLiu Ying dc_lb_mode(fu->lb, LB_NEUTRAL); 207*0e177d5cSLiu Ying } 208*0e177d5cSLiu Ying } 209*0e177d5cSLiu Ying 210*0e177d5cSLiu Ying static void dc_fu_set_layerblend(struct dc_fu *fu, struct dc_lb *lb) 211*0e177d5cSLiu Ying { 212*0e177d5cSLiu Ying fu->lb = lb; 213*0e177d5cSLiu Ying } 214*0e177d5cSLiu Ying 215*0e177d5cSLiu Ying static enum dc_link_id dc_fu_get_link_id(struct dc_fu *fu) 216*0e177d5cSLiu Ying { 217*0e177d5cSLiu Ying return fu->link_id; 218*0e177d5cSLiu Ying } 219*0e177d5cSLiu Ying 220*0e177d5cSLiu Ying static const char *dc_fu_get_name(struct dc_fu *fu) 221*0e177d5cSLiu Ying { 222*0e177d5cSLiu Ying return fu->name; 223*0e177d5cSLiu Ying } 224*0e177d5cSLiu Ying 225*0e177d5cSLiu Ying const struct dc_fu_ops dc_fu_common_ops = { 226*0e177d5cSLiu Ying .set_burstlength = dc_fu_set_burstlength, 227*0e177d5cSLiu Ying .set_baseaddress = dc_fu_set_baseaddress, 228*0e177d5cSLiu Ying .set_src_stride = dc_fu_set_src_stride, 229*0e177d5cSLiu Ying .set_src_buf_dimensions = dc_fu_set_src_buf_dimensions, 230*0e177d5cSLiu Ying .enable_src_buf = dc_fu_enable_src_buf, 231*0e177d5cSLiu Ying .disable_src_buf = dc_fu_disable_src_buf, 232*0e177d5cSLiu Ying .set_layerblend = dc_fu_set_layerblend, 233*0e177d5cSLiu Ying .get_link_id = dc_fu_get_link_id, 234*0e177d5cSLiu Ying .get_name = dc_fu_get_name, 235*0e177d5cSLiu Ying }; 236*0e177d5cSLiu Ying 237*0e177d5cSLiu Ying const struct dc_fu_ops *dc_fu_get_ops(struct dc_fu *fu) 238*0e177d5cSLiu Ying { 239*0e177d5cSLiu Ying return &fu->ops; 240*0e177d5cSLiu Ying } 241*0e177d5cSLiu Ying 242*0e177d5cSLiu Ying void dc_fu_common_hw_init(struct dc_fu *fu) 243*0e177d5cSLiu Ying { 244*0e177d5cSLiu Ying enum dc_fu_frac i; 245*0e177d5cSLiu Ying 246*0e177d5cSLiu Ying dc_fu_baddr_autoupdate(fu, 0x0); 247*0e177d5cSLiu Ying dc_fu_enable_shden(fu); 248*0e177d5cSLiu Ying dc_fu_set_linemode(fu, LINEMODE_DISPLAY); 249*0e177d5cSLiu Ying dc_fu_set_numbuffers(fu, 16); 250*0e177d5cSLiu Ying 251*0e177d5cSLiu Ying for (i = DC_FETCHUNIT_FRAC0; i < DC_FETCHUNIT_FRAC_NUM; i++) { 252*0e177d5cSLiu Ying dc_fu_layeroffset(fu, i, 0, 0); 253*0e177d5cSLiu Ying dc_fu_clipoffset(fu, i, 0, 0); 254*0e177d5cSLiu Ying dc_fu_clipdimensions(fu, i, 1, 1); 255*0e177d5cSLiu Ying dc_fu_disable_src_buf(fu, i); 256*0e177d5cSLiu Ying dc_fu_set_pixel_blend_mode(fu, i); 257*0e177d5cSLiu Ying } 258*0e177d5cSLiu Ying } 259