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

Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next

Here is the list of fixes that I have for drm/mali-dp. They've been on the mailing
lists for a while and merged into linux-next for a few weeks, but due to holiday and
travel to Linux Plumbers I did not send the pull request earlier. I don't know if
these patches can be pulled into v4.9 still (they will conflict with Ville Syrjälä's
cleanup of DRM_ROTATE series that is already in drm-next), but if you do that would
be great.

* 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld:
drm: mali-dp: Clear CVAL when leaving config mode
drm/arm: mark symbols static where possible
drm: mali-dp: Add support for setting plane's rotation property from userspace.
drm: mali-dp: Don't set DRM_PLANE_COMMIT_ACTIVE_ONLY
drm: mali-dp: Store internal format and n_planes in plane state
drm: mali-dp: Enable alpha blending
drm: mali-dp: Refactor plane initialisation
arm: mali-dp: Extract mode_config cleanup into malidp_fini
drm: mali-dp: Add pitch alignment check for planes
drm: mali-dp: Add pitch alignment check function
drm: mali-dp: Set the drm->irq_enabled flag to match driver's state.
drm: mali-dp: Clear the config_valid flag before using it in wait_event.

+92 -40
+13 -6
drivers/gpu/drm/arm/malidp_drv.c
··· 42 42 struct malidp_hw_device *hwdev = malidp->dev; 43 43 int ret; 44 44 45 + atomic_set(&malidp->config_valid, 0); 45 46 hwdev->set_config_valid(hwdev); 46 47 /* don't wait for config_valid flag if we are in config mode */ 47 48 if (hwdev->in_config_mode(hwdev)) ··· 92 91 93 92 drm_atomic_helper_commit_modeset_disables(drm, state); 94 93 drm_atomic_helper_commit_modeset_enables(drm, state); 95 - drm_atomic_helper_commit_planes(drm, state, 96 - DRM_PLANE_COMMIT_ACTIVE_ONLY); 94 + drm_atomic_helper_commit_planes(drm, state, 0); 97 95 98 96 malidp_atomic_commit_hw_done(state); 99 97 ··· 153 153 } 154 154 155 155 return 0; 156 + } 157 + 158 + static void malidp_fini(struct drm_device *drm) 159 + { 160 + malidp_de_planes_destroy(drm); 161 + drm_mode_config_cleanup(drm); 156 162 } 157 163 158 164 static int malidp_irq_init(struct platform_device *pdev) ··· 381 375 if (ret < 0) 382 376 goto irq_init_fail; 383 377 378 + drm->irq_enabled = true; 379 + 384 380 ret = drm_vblank_init(drm, drm->mode_config.num_crtc); 385 381 if (ret < 0) { 386 382 DRM_ERROR("failed to initialise vblank\n"); ··· 408 400 vblank_fail: 409 401 malidp_se_irq_fini(drm); 410 402 malidp_de_irq_fini(drm); 403 + drm->irq_enabled = false; 411 404 irq_init_fail: 412 405 component_unbind_all(dev, drm); 413 406 bind_fail: ··· 417 408 port_fail: 418 409 drm_dev_unregister(drm); 419 410 register_fail: 420 - malidp_de_planes_destroy(drm); 421 - drm_mode_config_cleanup(drm); 411 + malidp_fini(drm); 422 412 init_fail: 423 413 drm->dev_private = NULL; 424 414 dev_set_drvdata(dev, NULL); ··· 450 442 of_node_put(malidp->crtc.port); 451 443 malidp->crtc.port = NULL; 452 444 drm_dev_unregister(drm); 453 - malidp_de_planes_destroy(drm); 454 - drm_mode_config_cleanup(drm); 445 + malidp_fini(drm); 455 446 drm->dev_private = NULL; 456 447 dev_set_drvdata(dev, NULL); 457 448 clk_disable_unprepare(hwdev->mclk);
+3
drivers/gpu/drm/arm/malidp_drv.h
··· 39 39 40 40 /* size of the required rotation memory if plane is rotated */ 41 41 u32 rotmem_size; 42 + /* internal format ID */ 43 + u8 format; 44 + u8 n_planes; 42 45 }; 43 46 44 47 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
+5
drivers/gpu/drm/arm/malidp_hw.c
··· 125 125 { 126 126 u32 status, count = 100; 127 127 128 + malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID); 128 129 malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); 129 130 while (count) { 130 131 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); ··· 267 266 { 268 267 u32 status, count = 100; 269 268 269 + malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID); 270 270 malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); 271 271 while (count) { 272 272 status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); ··· 438 436 }, 439 437 .input_formats = malidp500_de_formats, 440 438 .n_input_formats = ARRAY_SIZE(malidp500_de_formats), 439 + .bus_align_bytes = 8, 441 440 }, 442 441 .query_hw = malidp500_query_hw, 443 442 .enter_config_mode = malidp500_enter_config_mode, ··· 471 468 }, 472 469 .input_formats = malidp550_de_formats, 473 470 .n_input_formats = ARRAY_SIZE(malidp550_de_formats), 471 + .bus_align_bytes = 8, 474 472 }, 475 473 .query_hw = malidp550_query_hw, 476 474 .enter_config_mode = malidp550_enter_config_mode, ··· 505 501 }, 506 502 .input_formats = malidp550_de_formats, 507 503 .n_input_formats = ARRAY_SIZE(malidp550_de_formats), 504 + .bus_align_bytes = 16, 508 505 }, 509 506 .query_hw = malidp650_query_hw, 510 507 .enter_config_mode = malidp550_enter_config_mode,
+9
drivers/gpu/drm/arm/malidp_hw.h
··· 88 88 /* list of supported input formats for each layer */ 89 89 const struct malidp_input_format *input_formats; 90 90 const u8 n_input_formats; 91 + 92 + /* pitch alignment requirement in bytes */ 93 + const u8 bus_align_bytes; 91 94 }; 92 95 93 96 struct malidp_hw_device { ··· 231 228 232 229 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, 233 230 u8 layer_id, u32 format); 231 + 232 + static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev, 233 + unsigned int pitch) 234 + { 235 + return !(pitch & (hwdev->map.bus_align_bytes - 1)); 236 + } 234 237 235 238 /* 236 239 * background color components are defined as 12bits values,
+62 -34
drivers/gpu/drm/arm/malidp_planes.c
··· 27 27 #define LAYER_H_FLIP (1 << 10) 28 28 #define LAYER_V_FLIP (1 << 11) 29 29 #define LAYER_ROT_MASK (0xf << 8) 30 + #define LAYER_COMP_MASK (0x3 << 12) 31 + #define LAYER_COMP_PIXEL (0x3 << 12) 32 + #define LAYER_COMP_PLANE (0x2 << 12) 33 + #define MALIDP_LAYER_COMPOSE 0x008 30 34 #define MALIDP_LAYER_SIZE 0x00c 31 35 #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) 32 36 #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) 33 37 #define MALIDP_LAYER_COMP_SIZE 0x010 34 38 #define MALIDP_LAYER_OFFSET 0x014 35 39 #define MALIDP_LAYER_STRIDE 0x018 40 + 41 + /* 42 + * This 4-entry look-up-table is used to determine the full 8-bit alpha value 43 + * for formats with 1- or 2-bit alpha channels. 44 + * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0% 45 + * opacity for 2-bit formats. 46 + */ 47 + #define MALIDP_ALPHA_LUT 0xffaa5500 36 48 37 49 static void malidp_de_plane_destroy(struct drm_plane *plane) 38 50 { ··· 58 46 devm_kfree(plane->dev->dev, mp); 59 47 } 60 48 61 - struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) 49 + static struct 50 + drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) 62 51 { 63 52 struct malidp_plane_state *state, *m_state; 64 53 ··· 71 58 m_state = to_malidp_plane_state(plane->state); 72 59 __drm_atomic_helper_plane_duplicate_state(plane, &state->base); 73 60 state->rotmem_size = m_state->rotmem_size; 61 + state->format = m_state->format; 62 + state->n_planes = m_state->n_planes; 74 63 } 75 64 76 65 return &state->base; 77 66 } 78 67 79 - void malidp_destroy_plane_state(struct drm_plane *plane, 80 - struct drm_plane_state *state) 68 + static void malidp_destroy_plane_state(struct drm_plane *plane, 69 + struct drm_plane_state *state) 81 70 { 82 71 struct malidp_plane_state *m_state = to_malidp_plane_state(state); 83 72 ··· 90 75 static const struct drm_plane_funcs malidp_de_plane_funcs = { 91 76 .update_plane = drm_atomic_helper_update_plane, 92 77 .disable_plane = drm_atomic_helper_disable_plane, 78 + .set_property = drm_atomic_helper_plane_set_property, 93 79 .destroy = malidp_de_plane_destroy, 94 80 .reset = drm_atomic_helper_plane_reset, 95 81 .atomic_duplicate_state = malidp_duplicate_plane_state, ··· 102 86 { 103 87 struct malidp_plane *mp = to_malidp_plane(plane); 104 88 struct malidp_plane_state *ms = to_malidp_plane_state(state); 105 - u8 format_id; 89 + struct drm_framebuffer *fb; 90 + int i; 106 91 u32 src_w, src_h; 107 92 108 93 if (!state->crtc || !state->fb) 109 94 return 0; 110 95 111 - format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, 112 - state->fb->pixel_format); 113 - if (format_id == MALIDP_INVALID_FORMAT_ID) 96 + fb = state->fb; 97 + 98 + ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, 99 + fb->pixel_format); 100 + if (ms->format == MALIDP_INVALID_FORMAT_ID) 114 101 return -EINVAL; 102 + 103 + ms->n_planes = drm_format_num_planes(fb->pixel_format); 104 + for (i = 0; i < ms->n_planes; i++) { 105 + if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) { 106 + DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n", 107 + fb->pitches[i], i); 108 + return -EINVAL; 109 + } 110 + } 115 111 116 112 src_w = state->src_w >> 16; 117 113 src_h = state->src_h >> 16; ··· 163 135 struct drm_gem_cma_object *obj; 164 136 struct malidp_plane *mp; 165 137 const struct malidp_hw_regmap *map; 166 - u8 format_id; 138 + struct malidp_plane_state *ms = to_malidp_plane_state(plane->state); 167 139 u16 ptr; 168 - u32 format, src_w, src_h, dest_w, dest_h, val = 0; 169 - int num_planes, i; 140 + u32 src_w, src_h, dest_w, dest_h, val; 141 + int i; 170 142 171 143 mp = to_malidp_plane(plane); 172 - 173 144 map = &mp->hwdev->map; 174 - format = plane->state->fb->pixel_format; 175 - format_id = malidp_hw_get_format_id(map, mp->layer->id, format); 176 - num_planes = drm_format_num_planes(format); 177 145 178 146 /* convert src values from Q16 fixed point to integer */ 179 147 src_w = plane->state->src_w >> 16; ··· 182 158 dest_h = plane->state->crtc_h; 183 159 } 184 160 185 - malidp_hw_write(mp->hwdev, format_id, mp->layer->base); 161 + malidp_hw_write(mp->hwdev, ms->format, mp->layer->base); 186 162 187 - for (i = 0; i < num_planes; i++) { 163 + for (i = 0; i < ms->n_planes; i++) { 188 164 /* calculate the offset for the layer's plane registers */ 189 165 ptr = mp->layer->ptr + (i << 4); 190 166 ··· 205 181 LAYER_V_VAL(plane->state->crtc_y), 206 182 mp->layer->base + MALIDP_LAYER_OFFSET); 207 183 208 - /* first clear the rotation bits in the register */ 209 - malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK, 210 - mp->layer->base + MALIDP_LAYER_CONTROL); 184 + /* first clear the rotation bits */ 185 + val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL); 186 + val &= ~LAYER_ROT_MASK; 211 187 212 188 /* setup the rotation and axis flip bits */ 213 189 if (plane->state->rotation & DRM_ROTATE_MASK) ··· 217 193 if (plane->state->rotation & DRM_REFLECT_Y) 218 194 val |= LAYER_H_FLIP; 219 195 196 + /* 197 + * always enable pixel alpha blending until we have a way to change 198 + * blend modes 199 + */ 200 + val &= ~LAYER_COMP_MASK; 201 + val |= LAYER_COMP_PIXEL; 202 + 220 203 /* set the 'enable layer' bit */ 221 204 val |= LAYER_ENABLE; 222 205 223 - malidp_hw_setbits(mp->hwdev, val, 224 - mp->layer->base + MALIDP_LAYER_CONTROL); 206 + malidp_hw_write(mp->hwdev, val, 207 + mp->layer->base + MALIDP_LAYER_CONTROL); 225 208 } 226 209 227 210 static void malidp_de_plane_disable(struct drm_plane *plane, ··· 253 222 struct malidp_plane *plane = NULL; 254 223 enum drm_plane_type plane_type; 255 224 unsigned long crtcs = 1 << drm->mode_config.num_crtc; 225 + unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 | 226 + DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y; 256 227 u32 *formats; 257 228 int ret, i, j, n; 258 229 ··· 287 254 if (ret < 0) 288 255 goto cleanup; 289 256 290 - /* SMART layer can't be rotated */ 291 - if (id != DE_SMART) { 292 - unsigned long flags = DRM_ROTATE_0 | 293 - DRM_ROTATE_90 | 294 - DRM_ROTATE_180 | 295 - DRM_ROTATE_270 | 296 - DRM_REFLECT_X | 297 - DRM_REFLECT_Y; 298 - drm_plane_create_rotation_property(&plane->base, 299 - DRM_ROTATE_0, 300 - flags); 301 - } 302 - 303 257 drm_plane_helper_add(&plane->base, 304 258 &malidp_de_plane_helper_funcs); 305 259 plane->hwdev = malidp->dev; 306 260 plane->layer = &map->layers[i]; 261 + 262 + /* Skip the features which the SMART layer doesn't have */ 263 + if (id == DE_SMART) 264 + continue; 265 + 266 + drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags); 267 + malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT, 268 + plane->layer->base + MALIDP_LAYER_COMPOSE); 307 269 } 308 270 309 271 kfree(formats);