Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: mali-dp: Add plane upscaling support

Enable the scaling engine for upscaling a single plane using the polyphase
scaler. No image enhancement support or downscaling yet*, and composition
result scaling is not implemented.

* Downscaling a plane requires mclk > pxlclk.

Signed-off-by: Mihail Atanassov <mihail.atanassov@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>

authored by

Mihail Atanassov and committed by
Liviu Dudau
28ce675b 50c7512f

+407 -17
+80
drivers/gpu/drm/arm/malidp_crtc.c
··· 247 247 return 0; 248 248 } 249 249 250 + static int malidp_crtc_atomic_check_scaling(struct drm_crtc *crtc, 251 + struct drm_crtc_state *state) 252 + { 253 + struct malidp_crtc_state *cs = to_malidp_crtc_state(state); 254 + struct malidp_se_config *s = &cs->scaler_config; 255 + struct drm_plane *plane; 256 + const struct drm_plane_state *pstate; 257 + u32 h_upscale_factor = 0; /* U16.16 */ 258 + u32 v_upscale_factor = 0; /* U16.16 */ 259 + u8 scaling = cs->scaled_planes_mask; 260 + 261 + if (!scaling) { 262 + s->scale_enable = false; 263 + return 0; 264 + } 265 + 266 + /* The scaling engine can only handle one plane at a time. */ 267 + if (scaling & (scaling - 1)) 268 + return -EINVAL; 269 + 270 + drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { 271 + struct malidp_plane *mp = to_malidp_plane(plane); 272 + u64 crtc_w, crtc_h; 273 + u32 phase; 274 + 275 + if (!(mp->layer->id & scaling)) 276 + continue; 277 + 278 + /* 279 + * Convert crtc_[w|h] to U32.32, then divide by U16.16 src_[w|h] 280 + * to get the U16.16 result. 281 + */ 282 + crtc_w = (u64)pstate->crtc_w << 32; 283 + crtc_h = (u64)pstate->crtc_h << 32; 284 + h_upscale_factor = (u32)(crtc_w / pstate->src_w); 285 + v_upscale_factor = (u32)(crtc_h / pstate->src_h); 286 + 287 + /* Downscaling won't work when mclk == pxlclk. */ 288 + if (!(h_upscale_factor >> 16) || !(v_upscale_factor >> 16)) 289 + return -EINVAL; 290 + 291 + s->input_w = pstate->src_w >> 16; 292 + s->input_h = pstate->src_h >> 16; 293 + s->output_w = pstate->crtc_w; 294 + s->output_h = pstate->crtc_h; 295 + 296 + #define SE_N_PHASE 4 297 + #define SE_SHIFT_N_PHASE 12 298 + /* Calculate initial_phase and delta_phase for horizontal. */ 299 + phase = s->input_w; 300 + s->h_init_phase = 301 + ((phase << SE_N_PHASE) / s->output_w + 1) / 2; 302 + 303 + phase = s->input_w; 304 + phase <<= (SE_SHIFT_N_PHASE + SE_N_PHASE); 305 + s->h_delta_phase = phase / s->output_w; 306 + 307 + /* Same for vertical. */ 308 + phase = s->input_h; 309 + s->v_init_phase = 310 + ((phase << SE_N_PHASE) / s->output_h + 1) / 2; 311 + 312 + phase = s->input_h; 313 + phase <<= (SE_SHIFT_N_PHASE + SE_N_PHASE); 314 + s->v_delta_phase = phase / s->output_h; 315 + #undef SE_N_PHASE 316 + #undef SE_SHIFT_N_PHASE 317 + s->plane_src_id = mp->layer->id; 318 + } 319 + 320 + s->scale_enable = true; 321 + s->hcoeff = malidp_se_select_coeffs(h_upscale_factor); 322 + s->vcoeff = malidp_se_select_coeffs(v_upscale_factor); 323 + return 0; 324 + } 325 + 250 326 static int malidp_crtc_atomic_check(struct drm_crtc *crtc, 251 327 struct drm_crtc_state *state) 252 328 { ··· 401 325 402 326 ret = malidp_crtc_atomic_check_gamma(crtc, state); 403 327 ret = ret ? ret : malidp_crtc_atomic_check_ctm(crtc, state); 328 + ret = ret ? ret : malidp_crtc_atomic_check_scaling(crtc, state); 404 329 405 330 return ret; 406 331 } ··· 430 353 sizeof(state->gamma_coeffs)); 431 354 memcpy(state->coloradj_coeffs, old_state->coloradj_coeffs, 432 355 sizeof(state->coloradj_coeffs)); 356 + memcpy(&state->scaler_config, &old_state->scaler_config, 357 + sizeof(state->scaler_config)); 358 + state->scaled_planes_mask = 0; 433 359 434 360 return &state->base; 435 361 }
+47
drivers/gpu/drm/arm/malidp_drv.c
··· 110 110 } 111 111 } 112 112 113 + static void malidp_atomic_commit_se_config(struct drm_crtc *crtc, 114 + struct drm_crtc_state *old_state) 115 + { 116 + struct malidp_crtc_state *cs = to_malidp_crtc_state(crtc->state); 117 + struct malidp_crtc_state *old_cs = to_malidp_crtc_state(old_state); 118 + struct malidp_drm *malidp = crtc_to_malidp_device(crtc); 119 + struct malidp_hw_device *hwdev = malidp->dev; 120 + struct malidp_se_config *s = &cs->scaler_config; 121 + struct malidp_se_config *old_s = &old_cs->scaler_config; 122 + u32 se_control = hwdev->map.se_base + 123 + ((hwdev->map.features & MALIDP_REGMAP_HAS_CLEARIRQ) ? 124 + 0x10 : 0xC); 125 + u32 layer_control = se_control + MALIDP_SE_LAYER_CONTROL; 126 + u32 scr = se_control + MALIDP_SE_SCALING_CONTROL; 127 + u32 val; 128 + 129 + /* Set SE_CONTROL */ 130 + if (!s->scale_enable) { 131 + val = malidp_hw_read(hwdev, se_control); 132 + val &= ~MALIDP_SE_SCALING_EN; 133 + malidp_hw_write(hwdev, val, se_control); 134 + return; 135 + } 136 + 137 + hwdev->se_set_scaling_coeffs(hwdev, s, old_s); 138 + val = malidp_hw_read(hwdev, se_control); 139 + val |= MALIDP_SE_SCALING_EN | MALIDP_SE_ALPHA_EN; 140 + 141 + val |= MALIDP_SE_RGBO_IF_EN; 142 + malidp_hw_write(hwdev, val, se_control); 143 + 144 + /* Set IN_SIZE & OUT_SIZE. */ 145 + val = MALIDP_SE_SET_V_SIZE(s->input_h) | 146 + MALIDP_SE_SET_H_SIZE(s->input_w); 147 + malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_IN_SIZE); 148 + val = MALIDP_SE_SET_V_SIZE(s->output_h) | 149 + MALIDP_SE_SET_H_SIZE(s->output_w); 150 + malidp_hw_write(hwdev, val, layer_control + MALIDP_SE_L0_OUT_SIZE); 151 + 152 + /* Set phase regs. */ 153 + malidp_hw_write(hwdev, s->h_init_phase, scr + MALIDP_SE_H_INIT_PH); 154 + malidp_hw_write(hwdev, s->h_delta_phase, scr + MALIDP_SE_H_DELTA_PH); 155 + malidp_hw_write(hwdev, s->v_init_phase, scr + MALIDP_SE_V_INIT_PH); 156 + malidp_hw_write(hwdev, s->v_delta_phase, scr + MALIDP_SE_V_DELTA_PH); 157 + } 158 + 113 159 /* 114 160 * set the "config valid" bit and wait until the hardware acts on it 115 161 */ ··· 225 179 for_each_crtc_in_state(state, crtc, old_crtc_state, i) { 226 180 malidp_atomic_commit_update_gamma(crtc, old_crtc_state); 227 181 malidp_atomic_commit_update_coloradj(crtc, old_crtc_state); 182 + malidp_atomic_commit_se_config(crtc, old_crtc_state); 228 183 } 229 184 230 185 drm_atomic_helper_commit_planes(drm, state, 0);
+3
drivers/gpu/drm/arm/malidp_drv.h
··· 53 53 struct drm_crtc_state base; 54 54 u32 gamma_coeffs[MALIDP_COEFFTAB_NUM_COEFFS]; 55 55 u32 coloradj_coeffs[MALIDP_COLORADJ_NUM_COEFFS]; 56 + struct malidp_se_config scaler_config; 57 + /* Bitfield of all the planes that have requested a scaled output. */ 58 + u8 scaled_planes_mask; 56 59 }; 57 60 58 61 #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base)
+140
drivers/gpu/drm/arm/malidp_hw.c
··· 86 86 { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE }, 87 87 }; 88 88 89 + #define SE_N_SCALING_COEFFS 96 90 + static const u16 dp500_se_scaling_coeffs[][SE_N_SCALING_COEFFS] = { 91 + [MALIDP_UPSCALING_COEFFS - 1] = { 92 + 0x0000, 0x0001, 0x0007, 0x0011, 0x001e, 0x002e, 0x003f, 0x0052, 93 + 0x0064, 0x0073, 0x007d, 0x0080, 0x007a, 0x006c, 0x0053, 0x002f, 94 + 0x0000, 0x3fc6, 0x3f83, 0x3f39, 0x3eea, 0x3e9b, 0x3e4f, 0x3e0a, 95 + 0x3dd4, 0x3db0, 0x3da2, 0x3db1, 0x3dde, 0x3e2f, 0x3ea5, 0x3f40, 96 + 0x0000, 0x00e5, 0x01ee, 0x0315, 0x0456, 0x05aa, 0x0709, 0x086c, 97 + 0x09c9, 0x0b15, 0x0c4a, 0x0d5d, 0x0e4a, 0x0f06, 0x0f91, 0x0fe5, 98 + 0x1000, 0x0fe5, 0x0f91, 0x0f06, 0x0e4a, 0x0d5d, 0x0c4a, 0x0b15, 99 + 0x09c9, 0x086c, 0x0709, 0x05aa, 0x0456, 0x0315, 0x01ee, 0x00e5, 100 + 0x0000, 0x3f40, 0x3ea5, 0x3e2f, 0x3dde, 0x3db1, 0x3da2, 0x3db0, 101 + 0x3dd4, 0x3e0a, 0x3e4f, 0x3e9b, 0x3eea, 0x3f39, 0x3f83, 0x3fc6, 102 + 0x0000, 0x002f, 0x0053, 0x006c, 0x007a, 0x0080, 0x007d, 0x0073, 103 + 0x0064, 0x0052, 0x003f, 0x002e, 0x001e, 0x0011, 0x0007, 0x0001 104 + }, 105 + [MALIDP_DOWNSCALING_1_5_COEFFS - 1] = { 106 + 0x0059, 0x004f, 0x0041, 0x002e, 0x0016, 0x3ffb, 0x3fd9, 0x3fb4, 107 + 0x3f8c, 0x3f62, 0x3f36, 0x3f09, 0x3edd, 0x3eb3, 0x3e8d, 0x3e6c, 108 + 0x3e52, 0x3e3f, 0x3e35, 0x3e37, 0x3e46, 0x3e61, 0x3e8c, 0x3ec5, 109 + 0x3f0f, 0x3f68, 0x3fd1, 0x004a, 0x00d3, 0x0169, 0x020b, 0x02b8, 110 + 0x036e, 0x042d, 0x04f2, 0x05b9, 0x0681, 0x0745, 0x0803, 0x08ba, 111 + 0x0965, 0x0a03, 0x0a91, 0x0b0d, 0x0b75, 0x0bc6, 0x0c00, 0x0c20, 112 + 0x0c28, 0x0c20, 0x0c00, 0x0bc6, 0x0b75, 0x0b0d, 0x0a91, 0x0a03, 113 + 0x0965, 0x08ba, 0x0803, 0x0745, 0x0681, 0x05b9, 0x04f2, 0x042d, 114 + 0x036e, 0x02b8, 0x020b, 0x0169, 0x00d3, 0x004a, 0x3fd1, 0x3f68, 115 + 0x3f0f, 0x3ec5, 0x3e8c, 0x3e61, 0x3e46, 0x3e37, 0x3e35, 0x3e3f, 116 + 0x3e52, 0x3e6c, 0x3e8d, 0x3eb3, 0x3edd, 0x3f09, 0x3f36, 0x3f62, 117 + 0x3f8c, 0x3fb4, 0x3fd9, 0x3ffb, 0x0016, 0x002e, 0x0041, 0x004f 118 + }, 119 + [MALIDP_DOWNSCALING_2_COEFFS - 1] = { 120 + 0x3f19, 0x3f03, 0x3ef0, 0x3edf, 0x3ed0, 0x3ec5, 0x3ebd, 0x3eb9, 121 + 0x3eb9, 0x3ebf, 0x3eca, 0x3ed9, 0x3eef, 0x3f0a, 0x3f2c, 0x3f52, 122 + 0x3f7f, 0x3fb0, 0x3fe8, 0x0026, 0x006a, 0x00b4, 0x0103, 0x0158, 123 + 0x01b1, 0x020d, 0x026c, 0x02cd, 0x032f, 0x0392, 0x03f4, 0x0455, 124 + 0x04b4, 0x051e, 0x0585, 0x05eb, 0x064c, 0x06a8, 0x06fe, 0x074e, 125 + 0x0796, 0x07d5, 0x080c, 0x0839, 0x085c, 0x0875, 0x0882, 0x0887, 126 + 0x0881, 0x0887, 0x0882, 0x0875, 0x085c, 0x0839, 0x080c, 0x07d5, 127 + 0x0796, 0x074e, 0x06fe, 0x06a8, 0x064c, 0x05eb, 0x0585, 0x051e, 128 + 0x04b4, 0x0455, 0x03f4, 0x0392, 0x032f, 0x02cd, 0x026c, 0x020d, 129 + 0x01b1, 0x0158, 0x0103, 0x00b4, 0x006a, 0x0026, 0x3fe8, 0x3fb0, 130 + 0x3f7f, 0x3f52, 0x3f2c, 0x3f0a, 0x3eef, 0x3ed9, 0x3eca, 0x3ebf, 131 + 0x3eb9, 0x3eb9, 0x3ebd, 0x3ec5, 0x3ed0, 0x3edf, 0x3ef0, 0x3f03 132 + }, 133 + [MALIDP_DOWNSCALING_2_75_COEFFS - 1] = { 134 + 0x3f51, 0x3f60, 0x3f71, 0x3f84, 0x3f98, 0x3faf, 0x3fc8, 0x3fe3, 135 + 0x0000, 0x001f, 0x0040, 0x0064, 0x008a, 0x00b1, 0x00da, 0x0106, 136 + 0x0133, 0x0160, 0x018e, 0x01bd, 0x01ec, 0x021d, 0x024e, 0x0280, 137 + 0x02b2, 0x02e4, 0x0317, 0x0349, 0x037c, 0x03ad, 0x03df, 0x0410, 138 + 0x0440, 0x0468, 0x048f, 0x04b3, 0x04d6, 0x04f8, 0x0516, 0x0533, 139 + 0x054e, 0x0566, 0x057c, 0x0590, 0x05a0, 0x05ae, 0x05ba, 0x05c3, 140 + 0x05c9, 0x05c3, 0x05ba, 0x05ae, 0x05a0, 0x0590, 0x057c, 0x0566, 141 + 0x054e, 0x0533, 0x0516, 0x04f8, 0x04d6, 0x04b3, 0x048f, 0x0468, 142 + 0x0440, 0x0410, 0x03df, 0x03ad, 0x037c, 0x0349, 0x0317, 0x02e4, 143 + 0x02b2, 0x0280, 0x024e, 0x021d, 0x01ec, 0x01bd, 0x018e, 0x0160, 144 + 0x0133, 0x0106, 0x00da, 0x00b1, 0x008a, 0x0064, 0x0040, 0x001f, 145 + 0x0000, 0x3fe3, 0x3fc8, 0x3faf, 0x3f98, 0x3f84, 0x3f71, 0x3f60 146 + }, 147 + [MALIDP_DOWNSCALING_4_COEFFS - 1] = { 148 + 0x0094, 0x00a9, 0x00be, 0x00d4, 0x00ea, 0x0101, 0x0118, 0x012f, 149 + 0x0148, 0x0160, 0x017a, 0x0193, 0x01ae, 0x01c8, 0x01e4, 0x01ff, 150 + 0x021c, 0x0233, 0x024a, 0x0261, 0x0278, 0x028f, 0x02a6, 0x02bd, 151 + 0x02d4, 0x02eb, 0x0302, 0x0319, 0x032f, 0x0346, 0x035d, 0x0374, 152 + 0x038a, 0x0397, 0x03a3, 0x03af, 0x03bb, 0x03c6, 0x03d1, 0x03db, 153 + 0x03e4, 0x03ed, 0x03f6, 0x03fe, 0x0406, 0x040d, 0x0414, 0x041a, 154 + 0x0420, 0x041a, 0x0414, 0x040d, 0x0406, 0x03fe, 0x03f6, 0x03ed, 155 + 0x03e4, 0x03db, 0x03d1, 0x03c6, 0x03bb, 0x03af, 0x03a3, 0x0397, 156 + 0x038a, 0x0374, 0x035d, 0x0346, 0x032f, 0x0319, 0x0302, 0x02eb, 157 + 0x02d4, 0x02bd, 0x02a6, 0x028f, 0x0278, 0x0261, 0x024a, 0x0233, 158 + 0x021c, 0x01ff, 0x01e4, 0x01c8, 0x01ae, 0x0193, 0x017a, 0x0160, 159 + 0x0148, 0x012f, 0x0118, 0x0101, 0x00ea, 0x00d4, 0x00be, 0x00a9 160 + }, 161 + }; 162 + 89 163 #define MALIDP_DE_DEFAULT_PREFETCH_START 5 90 164 91 165 static int malidp500_query_hw(struct malidp_hw_device *hwdev) ··· 283 209 * size = rotated_width * (bpp / 8) * 8; 284 210 */ 285 211 return w * drm_format_plane_cpp(fmt, 0) * 8; 212 + } 213 + 214 + static void malidp500_se_write_pp_coefftab(struct malidp_hw_device *hwdev, 215 + u32 direction, 216 + u16 addr, 217 + u8 coeffs_id) 218 + { 219 + int i; 220 + u16 scaling_control = MALIDP500_SE_CONTROL + MALIDP_SE_SCALING_CONTROL; 221 + 222 + malidp_hw_write(hwdev, 223 + direction | (addr & MALIDP_SE_COEFFTAB_ADDR_MASK), 224 + scaling_control + MALIDP_SE_COEFFTAB_ADDR); 225 + for (i = 0; i < ARRAY_SIZE(dp500_se_scaling_coeffs); ++i) 226 + malidp_hw_write(hwdev, MALIDP_SE_SET_COEFFTAB_DATA( 227 + dp500_se_scaling_coeffs[coeffs_id][i]), 228 + scaling_control + MALIDP_SE_COEFFTAB_DATA); 229 + } 230 + 231 + static int malidp500_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 232 + struct malidp_se_config *se_config, 233 + struct malidp_se_config *old_config) 234 + { 235 + /* Get array indices into dp500_se_scaling_coeffs. */ 236 + u8 h = (u8)se_config->hcoeff - 1; 237 + u8 v = (u8)se_config->vcoeff - 1; 238 + 239 + if (WARN_ON(h >= ARRAY_SIZE(dp500_se_scaling_coeffs) || 240 + v >= ARRAY_SIZE(dp500_se_scaling_coeffs))) 241 + return -EINVAL; 242 + 243 + if ((h == v) && (se_config->hcoeff != old_config->hcoeff || 244 + se_config->vcoeff != old_config->vcoeff)) { 245 + malidp500_se_write_pp_coefftab(hwdev, 246 + (MALIDP_SE_V_COEFFTAB | 247 + MALIDP_SE_H_COEFFTAB), 248 + 0, v); 249 + } else { 250 + if (se_config->vcoeff != old_config->vcoeff) 251 + malidp500_se_write_pp_coefftab(hwdev, 252 + MALIDP_SE_V_COEFFTAB, 253 + 0, v); 254 + if (se_config->hcoeff != old_config->hcoeff) 255 + malidp500_se_write_pp_coefftab(hwdev, 256 + MALIDP_SE_H_COEFFTAB, 257 + 0, h); 258 + } 259 + 260 + return 0; 286 261 } 287 262 288 263 static int malidp550_query_hw(struct malidp_hw_device *hwdev) ··· 507 384 return w * bytes_per_col; 508 385 } 509 386 387 + static int malidp550_se_set_scaling_coeffs(struct malidp_hw_device *hwdev, 388 + struct malidp_se_config *se_config, 389 + struct malidp_se_config *old_config) 390 + { 391 + u32 mask = MALIDP550_SE_CTL_VCSEL(MALIDP550_SE_CTL_SEL_MASK) | 392 + MALIDP550_SE_CTL_HCSEL(MALIDP550_SE_CTL_SEL_MASK); 393 + u32 new_value = MALIDP550_SE_CTL_VCSEL(se_config->vcoeff) | 394 + MALIDP550_SE_CTL_HCSEL(se_config->hcoeff); 395 + 396 + malidp_hw_clearbits(hwdev, mask, MALIDP550_SE_CONTROL); 397 + malidp_hw_setbits(hwdev, new_value, MALIDP550_SE_CONTROL); 398 + return 0; 399 + } 400 + 510 401 static int malidp650_query_hw(struct malidp_hw_device *hwdev) 511 402 { 512 403 u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); ··· 585 448 .set_config_valid = malidp500_set_config_valid, 586 449 .modeset = malidp500_modeset, 587 450 .rotmem_required = malidp500_rotmem_required, 451 + .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, 588 452 .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, 589 453 }, 590 454 [MALIDP_550] = { ··· 621 483 .set_config_valid = malidp550_set_config_valid, 622 484 .modeset = malidp550_modeset, 623 485 .rotmem_required = malidp550_rotmem_required, 486 + .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 624 487 .features = 0, 625 488 }, 626 489 [MALIDP_650] = { ··· 658 519 .set_config_valid = malidp550_set_config_valid, 659 520 .modeset = malidp550_modeset, 660 521 .rotmem_required = malidp550_rotmem_required, 522 + .se_set_scaling_coeffs = malidp550_se_set_scaling_coeffs, 661 523 .features = 0, 662 524 }, 663 525 };
+45
drivers/gpu/drm/arm/malidp_hw.h
··· 61 61 u16 stride_offset; /* Offset to the first stride register. */ 62 62 }; 63 63 64 + enum malidp_scaling_coeff_set { 65 + MALIDP_UPSCALING_COEFFS = 1, 66 + MALIDP_DOWNSCALING_1_5_COEFFS = 2, 67 + MALIDP_DOWNSCALING_2_COEFFS = 3, 68 + MALIDP_DOWNSCALING_2_75_COEFFS = 4, 69 + MALIDP_DOWNSCALING_4_COEFFS = 5, 70 + }; 71 + 72 + struct malidp_se_config { 73 + u8 scale_enable : 1; 74 + u8 hcoeff : 3; 75 + u8 vcoeff : 3; 76 + u8 plane_src_id; 77 + u16 input_w, input_h; 78 + u16 output_w, output_h; 79 + u32 h_init_phase, h_delta_phase; 80 + u32 v_init_phase, v_delta_phase; 81 + }; 82 + 64 83 /* regmap features */ 65 84 #define MALIDP_REGMAP_HAS_CLEARIRQ (1 << 0) 66 85 ··· 171 152 * and the buffer format. 172 153 */ 173 154 int (*rotmem_required)(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt); 155 + 156 + int (*se_set_scaling_coeffs)(struct malidp_hw_device *hwdev, 157 + struct malidp_se_config *se_config, 158 + struct malidp_se_config *old_config); 174 159 175 160 u8 features; 176 161 ··· 273 250 return !(pitch & (hwdev->map.bus_align_bytes - 1)); 274 251 } 275 252 253 + /* U16.16 */ 254 + #define FP_1_00000 0x00010000 /* 1.0 */ 255 + #define FP_0_66667 0x0000AAAA /* 0.6667 = 1/1.5 */ 256 + #define FP_0_50000 0x00008000 /* 0.5 = 1/2 */ 257 + #define FP_0_36363 0x00005D17 /* 0.36363 = 1/2.75 */ 258 + #define FP_0_25000 0x00004000 /* 0.25 = 1/4 */ 259 + 260 + static inline enum malidp_scaling_coeff_set 261 + malidp_se_select_coeffs(u32 upscale_factor) 262 + { 263 + return (upscale_factor >= FP_1_00000) ? MALIDP_UPSCALING_COEFFS : 264 + (upscale_factor >= FP_0_66667) ? MALIDP_DOWNSCALING_1_5_COEFFS : 265 + (upscale_factor >= FP_0_50000) ? MALIDP_DOWNSCALING_2_COEFFS : 266 + (upscale_factor >= FP_0_36363) ? MALIDP_DOWNSCALING_2_75_COEFFS : 267 + MALIDP_DOWNSCALING_4_COEFFS; 268 + } 269 + 270 + #undef FP_0_25000 271 + #undef FP_0_36363 272 + #undef FP_0_50000 273 + #undef FP_0_66667 274 + #undef FP_1_00000 276 275 /* 277 276 * background color components are defined as 12bits values, 278 277 * they will be shifted right when stored on hardware that
+56 -17
drivers/gpu/drm/arm/malidp_planes.c
··· 25 25 #define MALIDP_LAYER_FORMAT 0x000 26 26 #define MALIDP_LAYER_CONTROL 0x004 27 27 #define LAYER_ENABLE (1 << 0) 28 + #define LAYER_FLOWCFG_MASK 7 29 + #define LAYER_FLOWCFG(x) (((x) & LAYER_FLOWCFG_MASK) << 1) 30 + #define LAYER_FLOWCFG_SCALE_SE 3 28 31 #define LAYER_ROT_OFFSET 8 29 32 #define LAYER_H_FLIP (1 << 10) 30 33 #define LAYER_V_FLIP (1 << 11) ··· 136 133 .atomic_print_state = malidp_plane_atomic_print_state, 137 134 }; 138 135 136 + static int malidp_se_check_scaling(struct malidp_plane *mp, 137 + struct drm_plane_state *state) 138 + { 139 + struct drm_crtc_state *crtc_state = 140 + drm_atomic_get_existing_crtc_state(state->state, state->crtc); 141 + struct malidp_crtc_state *mc; 142 + struct drm_rect clip = { 0 }; 143 + u32 src_w, src_h; 144 + int ret; 145 + 146 + if (!crtc_state) 147 + return -EINVAL; 148 + 149 + clip.x2 = crtc_state->adjusted_mode.hdisplay; 150 + clip.y2 = crtc_state->adjusted_mode.vdisplay; 151 + ret = drm_plane_helper_check_state(state, &clip, 0, INT_MAX, true, true); 152 + if (ret) 153 + return ret; 154 + 155 + src_w = state->src_w >> 16; 156 + src_h = state->src_h >> 16; 157 + if ((state->crtc_w == src_w) && (state->crtc_h == src_h)) { 158 + /* Scaling not necessary for this plane. */ 159 + mc->scaled_planes_mask &= ~(mp->layer->id); 160 + return 0; 161 + } 162 + 163 + if (mp->layer->id & (DE_SMART | DE_GRAPHICS2)) 164 + return -EINVAL; 165 + 166 + mc = to_malidp_crtc_state(crtc_state); 167 + 168 + mc->scaled_planes_mask |= mp->layer->id; 169 + /* Defer scaling requirements calculation to the crtc check. */ 170 + return 0; 171 + } 172 + 139 173 static int malidp_de_plane_check(struct drm_plane *plane, 140 174 struct drm_plane_state *state) 141 175 { 142 176 struct malidp_plane *mp = to_malidp_plane(plane); 143 177 struct malidp_plane_state *ms = to_malidp_plane_state(state); 144 - struct drm_crtc_state *crtc_state; 145 178 struct drm_framebuffer *fb; 146 - struct drm_rect clip = { 0 }; 147 179 int i, ret; 148 - u32 src_w, src_h; 149 180 150 181 if (!state->crtc || !state->fb) 151 182 return 0; ··· 200 163 } 201 164 } 202 165 203 - src_w = state->src_w >> 16; 204 - src_h = state->src_h >> 16; 205 - 206 166 if ((state->crtc_w > mp->hwdev->max_line_size) || 207 167 (state->crtc_h > mp->hwdev->max_line_size) || 208 168 (state->crtc_w < mp->hwdev->min_line_size) || ··· 216 182 (state->fb->pitches[1] != state->fb->pitches[2])) 217 183 return -EINVAL; 218 184 185 + ret = malidp_se_check_scaling(mp, state); 186 + if (ret) 187 + return ret; 188 + 219 189 /* packed RGB888 / BGR888 can't be rotated or flipped */ 220 190 if (state->rotation != DRM_ROTATE_0 && 221 191 (fb->format->format == DRM_FORMAT_RGB888 || 222 192 fb->format->format == DRM_FORMAT_BGR888)) 223 193 return -EINVAL; 224 - 225 - crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc); 226 - clip.x2 = crtc_state->adjusted_mode.hdisplay; 227 - clip.y2 = crtc_state->adjusted_mode.vdisplay; 228 - ret = drm_plane_helper_check_state(state, &clip, 229 - DRM_PLANE_HELPER_NO_SCALING, 230 - DRM_PLANE_HELPER_NO_SCALING, 231 - true, true); 232 - if (ret) 233 - return ret; 234 194 235 195 ms->rotmem_size = 0; 236 196 if (state->rotation & MALIDP_ROTATED_MASK) { ··· 330 302 val &= ~LAYER_COMP_MASK; 331 303 val |= LAYER_COMP_PIXEL; 332 304 305 + val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK); 306 + if (plane->state->crtc) { 307 + struct malidp_crtc_state *m = 308 + to_malidp_crtc_state(plane->state->crtc->state); 309 + 310 + if (m->scaler_config.scale_enable && 311 + m->scaler_config.plane_src_id == mp->layer->id) 312 + val |= LAYER_FLOWCFG(LAYER_FLOWCFG_SCALE_SE); 313 + } 314 + 333 315 /* set the 'enable layer' bit */ 334 316 val |= LAYER_ENABLE; 335 317 ··· 352 314 { 353 315 struct malidp_plane *mp = to_malidp_plane(plane); 354 316 355 - malidp_hw_clearbits(mp->hwdev, LAYER_ENABLE, 317 + malidp_hw_clearbits(mp->hwdev, 318 + LAYER_ENABLE | LAYER_FLOWCFG(LAYER_FLOWCFG_MASK), 356 319 mp->layer->base + MALIDP_LAYER_CONTROL); 357 320 } 358 321
+36
drivers/gpu/drm/arm/malidp_regs.h
··· 106 106 #define MALIDP_COEF_TABLE_ADDR 0x00030 107 107 #define MALIDP_COEF_TABLE_DATA 0x00034 108 108 109 + /* Scaling engine registers and masks. */ 110 + #define MALIDP_SE_SCALING_EN (1 << 0) 111 + #define MALIDP_SE_ALPHA_EN (1 << 1) 112 + #define MALIDP_SE_RGBO_IF_EN (1 << 4) 113 + #define MALIDP550_SE_CTL_SEL_MASK 7 114 + #define MALIDP550_SE_CTL_VCSEL(x) \ 115 + (((x) & MALIDP550_SE_CTL_SEL_MASK) << 20) 116 + #define MALIDP550_SE_CTL_HCSEL(x) \ 117 + (((x) & MALIDP550_SE_CTL_SEL_MASK) << 16) 118 + 119 + /* Blocks with offsets from SE_CONTROL register. */ 120 + #define MALIDP_SE_LAYER_CONTROL 0x14 121 + #define MALIDP_SE_L0_IN_SIZE 0x00 122 + #define MALIDP_SE_L0_OUT_SIZE 0x04 123 + #define MALIDP_SE_SET_V_SIZE(x) (((x) & 0x1fff) << 16) 124 + #define MALIDP_SE_SET_H_SIZE(x) (((x) & 0x1fff) << 0) 125 + #define MALIDP_SE_SCALING_CONTROL 0x24 126 + #define MALIDP_SE_H_INIT_PH 0x00 127 + #define MALIDP_SE_H_DELTA_PH 0x04 128 + #define MALIDP_SE_V_INIT_PH 0x08 129 + #define MALIDP_SE_V_DELTA_PH 0x0c 130 + #define MALIDP_SE_COEFFTAB_ADDR 0x10 131 + #define MALIDP_SE_COEFFTAB_ADDR_MASK 0x7f 132 + #define MALIDP_SE_V_COEFFTAB (1 << 8) 133 + #define MALIDP_SE_H_COEFFTAB (1 << 9) 134 + #define MALIDP_SE_SET_V_COEFFTAB_ADDR(x) \ 135 + (MALIDP_SE_V_COEFFTAB | ((x) & MALIDP_SE_COEFFTAB_ADDR_MASK)) 136 + #define MALIDP_SE_SET_H_COEFFTAB_ADDR(x) \ 137 + (MALIDP_SE_H_COEFFTAB | ((x) & MALIDP_SE_COEFFTAB_ADDR_MASK)) 138 + #define MALIDP_SE_COEFFTAB_DATA 0x14 139 + #define MALIDP_SE_COEFFTAB_DATA_MASK 0x3fff 140 + #define MALIDP_SE_SET_COEFFTAB_DATA(x) \ 141 + ((x) & MALIDP_SE_COEFFTAB_DATA_MASK) 142 + 109 143 /* register offsets and bits specific to DP500 */ 110 144 #define MALIDP500_ADDR_SPACE_SIZE 0x01000 111 145 #define MALIDP500_DC_BASE 0x00000 ··· 180 146 #define MALIDP500_DE_LG2_BASE 0x00300 181 147 #define MALIDP500_DE_LG2_PTR_BASE 0x0031c 182 148 #define MALIDP500_SE_BASE 0x00c00 149 + #define MALIDP500_SE_CONTROL 0x00c0c 183 150 #define MALIDP500_SE_PTR_BASE 0x00e0c 184 151 #define MALIDP500_DC_IRQ_BASE 0x00f00 185 152 #define MALIDP500_CONFIG_VALID 0x00f00 ··· 210 175 #define MALIDP550_DE_LS_PTR_BASE 0x0042c 211 176 #define MALIDP550_DE_PERF_BASE 0x00500 212 177 #define MALIDP550_SE_BASE 0x08000 178 + #define MALIDP550_SE_CONTROL 0x08010 213 179 #define MALIDP550_DC_BASE 0x0c000 214 180 #define MALIDP550_DC_CONTROL 0x0c010 215 181 #define MALIDP550_DC_CONFIG_REQ (1 << 16)