Lines Matching +full:sun6i +full:- +full:a31 +full:- +full:dma

1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
14 #include <linux/dma-mapping.h>
34 /* backend <-> TCON muxing selection done in backend */
54 regmap_write(engine->regs, SUN4I_BACKEND_OCCTL_REG, in sun4i_backend_apply_color_correction()
58 regmap_write(engine->regs, SUN4I_BACKEND_OCRCOEF_REG(i), in sun4i_backend_apply_color_correction()
67 regmap_update_bits(engine->regs, SUN4I_BACKEND_OCCTL_REG, in sun4i_backend_disable_color_correction()
75 regmap_write(engine->regs, SUN4I_BACKEND_REGBUFFCTL_REG, in sun4i_backend_commit()
93 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, in sun4i_backend_layer_enable()
133 return -EINVAL; in sun4i_backend_drm_format_to_layer()
171 struct drm_plane_state *state = plane->state; in sun4i_backend_update_layer_coord()
175 if (plane->type == DRM_PLANE_TYPE_PRIMARY) { in sun4i_backend_update_layer_coord()
177 state->crtc_w, state->crtc_h); in sun4i_backend_update_layer_coord()
178 regmap_write(backend->engine.regs, SUN4I_BACKEND_DISSIZE_REG, in sun4i_backend_update_layer_coord()
179 SUN4I_BACKEND_DISSIZE(state->crtc_w, in sun4i_backend_update_layer_coord()
180 state->crtc_h)); in sun4i_backend_update_layer_coord()
185 state->crtc_w, state->crtc_h); in sun4i_backend_update_layer_coord()
186 regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYSIZE_REG(layer), in sun4i_backend_update_layer_coord()
187 SUN4I_BACKEND_LAYSIZE(state->crtc_w, in sun4i_backend_update_layer_coord()
188 state->crtc_h)); in sun4i_backend_update_layer_coord()
192 state->crtc_x, state->crtc_y); in sun4i_backend_update_layer_coord()
193 regmap_write(backend->engine.regs, SUN4I_BACKEND_LAYCOOR_REG(layer), in sun4i_backend_update_layer_coord()
194 SUN4I_BACKEND_LAYCOOR(state->crtc_x, in sun4i_backend_update_layer_coord()
195 state->crtc_y)); in sun4i_backend_update_layer_coord()
203 struct drm_plane_state *state = plane->state; in sun4i_backend_update_yuv_format()
204 struct drm_framebuffer *fb = state->fb; in sun4i_backend_update_yuv_format()
205 const struct drm_format_info *format = fb->format; in sun4i_backend_update_yuv_format()
206 const uint32_t fmt = format->format; in sun4i_backend_update_yuv_format()
211 regmap_write(backend->engine.regs, in sun4i_backend_update_yuv_format()
219 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), in sun4i_backend_update_yuv_format()
223 /* TODO: Add support for the multi-planar YUV formats */ in sun4i_backend_update_yuv_format()
252 regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVCTL_REG, val); in sun4i_backend_update_yuv_format()
260 struct drm_plane_state *state = plane->state; in sun4i_backend_update_layer_formats()
261 struct drm_framebuffer *fb = state->fb; in sun4i_backend_update_layer_formats()
267 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), in sun4i_backend_update_layer_formats()
270 if (plane->state->crtc) in sun4i_backend_update_layer_formats()
271 interlaced = plane->state->crtc->state->adjusted_mode.flags in sun4i_backend_update_layer_formats()
274 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, in sun4i_backend_update_layer_formats()
281 val = SUN4I_BACKEND_ATTCTL_REG0_LAY_GLBALPHA(state->alpha >> 8); in sun4i_backend_update_layer_formats()
282 if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) in sun4i_backend_update_layer_formats()
284 regmap_update_bits(backend->engine.regs, in sun4i_backend_update_layer_formats()
290 if (fb->format->is_yuv) in sun4i_backend_update_layer_formats()
293 ret = sun4i_backend_drm_format_to_layer(fb->format->format, &val); in sun4i_backend_update_layer_formats()
299 regmap_update_bits(backend->engine.regs, in sun4i_backend_update_layer_formats()
318 regmap_update_bits(backend->engine.regs, in sun4i_backend_update_layer_frontend()
323 regmap_update_bits(backend->engine.regs, in sun4i_backend_update_layer_frontend()
334 /* TODO: Add support for the multi-planar YUV formats */ in sun4i_backend_update_yuv_buffer()
336 regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVADD_REG(0), paddr); in sun4i_backend_update_yuv_buffer()
338 DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8); in sun4i_backend_update_yuv_buffer()
339 regmap_write(backend->engine.regs, SUN4I_BACKEND_IYUVLINEWIDTH_REG(0), in sun4i_backend_update_yuv_buffer()
340 fb->pitches[0] * 8); in sun4i_backend_update_yuv_buffer()
348 struct drm_plane_state *state = plane->state; in sun4i_backend_update_layer_buffer()
349 struct drm_framebuffer *fb = state->fb; in sun4i_backend_update_layer_buffer()
354 DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8); in sun4i_backend_update_layer_buffer()
355 regmap_write(backend->engine.regs, in sun4i_backend_update_layer_buffer()
357 fb->pitches[0] * 8); in sun4i_backend_update_layer_buffer()
363 if (fb->format->is_yuv) in sun4i_backend_update_layer_buffer()
369 regmap_write(backend->engine.regs, in sun4i_backend_update_layer_buffer()
376 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG, in sun4i_backend_update_layer_buffer()
386 struct drm_plane_state *state = plane->state; in sun4i_backend_update_layer_zpos()
388 unsigned int priority = state->normalized_zpos; in sun4i_backend_update_layer_zpos()
389 unsigned int pipe = p_state->pipe; in sun4i_backend_update_layer_zpos()
393 regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_ATTCTL_REG0(layer), in sun4i_backend_update_layer_zpos()
396 SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(p_state->pipe) | in sun4i_backend_update_layer_zpos()
405 regmap_update_bits(backend->engine.regs, in sun4i_backend_cleanup_layer()
413 u16 src_h = state->src_h >> 16; in sun4i_backend_plane_uses_scaler()
414 u16 src_w = state->src_w >> 16; in sun4i_backend_plane_uses_scaler()
417 src_w, src_h, state->crtc_w, state->crtc_h); in sun4i_backend_plane_uses_scaler()
419 if ((state->crtc_h != src_h) || (state->crtc_w != src_w)) in sun4i_backend_plane_uses_scaler()
427 struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); in sun4i_backend_plane_uses_frontend()
428 struct sun4i_backend *backend = layer->backend; in sun4i_backend_plane_uses_frontend()
429 uint32_t format = state->fb->format->format; in sun4i_backend_plane_uses_frontend()
430 uint64_t modifier = state->fb->modifier; in sun4i_backend_plane_uses_frontend()
432 if (IS_ERR(backend->frontend)) in sun4i_backend_plane_uses_frontend()
480 WARN_ON(regmap_read_poll_timeout(engine->regs, in sun4i_backend_atomic_begin()
491 struct drm_atomic_state *state = crtc_state->state; in sun4i_backend_atomic_check()
492 struct drm_device *drm = state->dev; in sun4i_backend_atomic_check()
504 if (!crtc_state->planes_changed) in sun4i_backend_atomic_check()
507 drm_for_each_plane_mask(plane, drm, crtc_state->plane_mask) { in sun4i_backend_atomic_check()
512 struct drm_framebuffer *fb = plane_state->fb; in sun4i_backend_atomic_check()
516 &layer_state->uses_frontend)) in sun4i_backend_atomic_check()
517 return -EINVAL; in sun4i_backend_atomic_check()
519 if (layer_state->uses_frontend) { in sun4i_backend_atomic_check()
521 plane->index); in sun4i_backend_atomic_check()
524 if (fb->format->is_yuv) { in sun4i_backend_atomic_check()
531 drm_get_format_name(fb->format->format, in sun4i_backend_atomic_check()
533 if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) in sun4i_backend_atomic_check()
537 plane_state->normalized_zpos); in sun4i_backend_atomic_check()
540 plane_states[plane_state->normalized_zpos] = plane_state; in sun4i_backend_atomic_check()
564 * This two-step scenario makes us unable to guarantee a in sun4i_backend_atomic_check()
583 if (backend->quirks->supports_lowest_plane_alpha) in sun4i_backend_atomic_check()
588 return -EINVAL; in sun4i_backend_atomic_check()
592 if (!backend->quirks->supports_lowest_plane_alpha && in sun4i_backend_atomic_check()
593 (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE)) in sun4i_backend_atomic_check()
594 return -EINVAL; in sun4i_backend_atomic_check()
598 struct drm_framebuffer *fb = p_state->fb; in sun4i_backend_atomic_check()
605 if (fb->format->has_alpha || (p_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) in sun4i_backend_atomic_check()
608 s_state->pipe = current_pipe; in sun4i_backend_atomic_check()
614 return -EINVAL; in sun4i_backend_atomic_check()
619 return -EINVAL; in sun4i_backend_atomic_check()
632 struct sun4i_frontend *frontend = backend->frontend; in sun4i_backend_vblank_quirk()
651 spin_lock(&backend->frontend_lock); in sun4i_backend_vblank_quirk()
652 if (backend->frontend_teardown) { in sun4i_backend_vblank_quirk()
654 backend->frontend_teardown = false; in sun4i_backend_vblank_quirk()
656 spin_unlock(&backend->frontend_lock); in sun4i_backend_vblank_quirk()
663 backend->sat_reset = devm_reset_control_get(dev, "sat"); in sun4i_backend_init_sat()
664 if (IS_ERR(backend->sat_reset)) { in sun4i_backend_init_sat()
666 return PTR_ERR(backend->sat_reset); in sun4i_backend_init_sat()
669 ret = reset_control_deassert(backend->sat_reset); in sun4i_backend_init_sat()
675 backend->sat_clk = devm_clk_get(dev, "sat"); in sun4i_backend_init_sat()
676 if (IS_ERR(backend->sat_clk)) { in sun4i_backend_init_sat()
678 ret = PTR_ERR(backend->sat_clk); in sun4i_backend_init_sat()
682 ret = clk_prepare_enable(backend->sat_clk); in sun4i_backend_init_sat()
691 reset_control_assert(backend->sat_reset); in sun4i_backend_init_sat()
698 clk_disable_unprepare(backend->sat_clk); in sun4i_backend_free_sat()
699 reset_control_assert(backend->sat_reset); in sun4i_backend_free_sat()
718 ep = of_graph_get_endpoint_by_regs(node, 0, -1); in sun4i_backend_of_get_id()
720 return -EINVAL; in sun4i_backend_of_get_id()
725 return -EINVAL; in sun4i_backend_of_get_id()
741 return ERR_PTR(-EINVAL); in sun4i_backend_find_frontend()
750 list_for_each_entry(frontend, &drv->frontend_list, list) { in sun4i_backend_find_frontend()
751 if (remote == frontend->node) { in sun4i_backend_find_frontend()
759 return ERR_PTR(-EINVAL); in sun4i_backend_find_frontend()
784 struct sun4i_drv *drv = drm->dev_private; in sun4i_backend_bind()
793 return -ENOMEM; in sun4i_backend_bind()
795 spin_lock_init(&backend->frontend_lock); in sun4i_backend_bind()
797 if (of_find_property(dev->of_node, "interconnects", NULL)) { in sun4i_backend_bind()
799 * This assume we have the same DMA constraints for all our the in sun4i_backend_bind()
802 * for us, and DRM doesn't do per-device allocation either, so in sun4i_backend_bind()
805 ret = of_dma_configure(drm->dev, dev->of_node, true); in sun4i_backend_bind()
811 * because of an old DT, we need to set the DMA offset by hand in sun4i_backend_bind()
812 * on our device since the RAM mapping is at 0 for the DMA bus, in sun4i_backend_bind()
819 * returns -EINVAL. Unfortunately, this happens when we have two in sun4i_backend_bind()
824 ret = dma_direct_set_offset(drm->dev, PHYS_OFFSET, 0, SZ_4G); in sun4i_backend_bind()
825 if (ret && ret != -EINVAL) in sun4i_backend_bind()
829 backend->engine.node = dev->of_node; in sun4i_backend_bind()
830 backend->engine.ops = &sun4i_backend_engine_ops; in sun4i_backend_bind()
831 backend->engine.id = sun4i_backend_of_get_id(dev->of_node); in sun4i_backend_bind()
832 if (backend->engine.id < 0) in sun4i_backend_bind()
833 return backend->engine.id; in sun4i_backend_bind()
835 backend->frontend = sun4i_backend_find_frontend(drv, dev->of_node); in sun4i_backend_bind()
836 if (IS_ERR(backend->frontend)) in sun4i_backend_bind()
844 backend->reset = devm_reset_control_get(dev, NULL); in sun4i_backend_bind()
845 if (IS_ERR(backend->reset)) { in sun4i_backend_bind()
847 return PTR_ERR(backend->reset); in sun4i_backend_bind()
850 ret = reset_control_deassert(backend->reset); in sun4i_backend_bind()
856 backend->bus_clk = devm_clk_get(dev, "ahb"); in sun4i_backend_bind()
857 if (IS_ERR(backend->bus_clk)) { in sun4i_backend_bind()
859 ret = PTR_ERR(backend->bus_clk); in sun4i_backend_bind()
862 clk_prepare_enable(backend->bus_clk); in sun4i_backend_bind()
864 backend->mod_clk = devm_clk_get(dev, "mod"); in sun4i_backend_bind()
865 if (IS_ERR(backend->mod_clk)) { in sun4i_backend_bind()
867 ret = PTR_ERR(backend->mod_clk); in sun4i_backend_bind()
871 ret = clk_set_rate_exclusive(backend->mod_clk, 300000000); in sun4i_backend_bind()
877 clk_prepare_enable(backend->mod_clk); in sun4i_backend_bind()
879 backend->ram_clk = devm_clk_get(dev, "ram"); in sun4i_backend_bind()
880 if (IS_ERR(backend->ram_clk)) { in sun4i_backend_bind()
882 ret = PTR_ERR(backend->ram_clk); in sun4i_backend_bind()
885 clk_prepare_enable(backend->ram_clk); in sun4i_backend_bind()
887 if (of_device_is_compatible(dev->of_node, in sun4i_backend_bind()
888 "allwinner,sun8i-a33-display-backend")) { in sun4i_backend_bind()
896 backend->engine.regs = devm_regmap_init_mmio(dev, regs, in sun4i_backend_bind()
898 if (IS_ERR(backend->engine.regs)) { in sun4i_backend_bind()
900 return PTR_ERR(backend->engine.regs); in sun4i_backend_bind()
903 list_add_tail(&backend->engine.list, &drv->engine_list); in sun4i_backend_bind()
914 regmap_write(backend->engine.regs, i, 0); in sun4i_backend_bind()
917 regmap_write(backend->engine.regs, SUN4I_BACKEND_REGBUFFCTL_REG, in sun4i_backend_bind()
921 regmap_write(backend->engine.regs, SUN4I_BACKEND_MODCTL_REG, in sun4i_backend_bind()
927 if (quirks->needs_output_muxing) { in sun4i_backend_bind()
938 regmap_update_bits(backend->engine.regs, in sun4i_backend_bind()
941 (backend->engine.id in sun4i_backend_bind()
946 backend->quirks = quirks; in sun4i_backend_bind()
951 clk_disable_unprepare(backend->ram_clk); in sun4i_backend_bind()
953 clk_rate_exclusive_put(backend->mod_clk); in sun4i_backend_bind()
954 clk_disable_unprepare(backend->mod_clk); in sun4i_backend_bind()
956 clk_disable_unprepare(backend->bus_clk); in sun4i_backend_bind()
958 reset_control_assert(backend->reset); in sun4i_backend_bind()
967 list_del(&backend->engine.list); in sun4i_backend_unbind()
969 if (of_device_is_compatible(dev->of_node, in sun4i_backend_unbind()
970 "allwinner,sun8i-a33-display-backend")) in sun4i_backend_unbind()
973 clk_disable_unprepare(backend->ram_clk); in sun4i_backend_unbind()
974 clk_rate_exclusive_put(backend->mod_clk); in sun4i_backend_unbind()
975 clk_disable_unprepare(backend->mod_clk); in sun4i_backend_unbind()
976 clk_disable_unprepare(backend->bus_clk); in sun4i_backend_unbind()
977 reset_control_assert(backend->reset); in sun4i_backend_unbind()
987 return component_add(&pdev->dev, &sun4i_backend_ops); in sun4i_backend_probe()
992 component_del(&pdev->dev, &sun4i_backend_ops); in sun4i_backend_remove()
1020 .compatible = "allwinner,sun4i-a10-display-backend",
1024 .compatible = "allwinner,sun5i-a13-display-backend",
1028 .compatible = "allwinner,sun6i-a31-display-backend",
1032 .compatible = "allwinner,sun7i-a20-display-backend",
1036 .compatible = "allwinner,sun8i-a23-display-backend",
1040 .compatible = "allwinner,sun8i-a33-display-backend",
1044 .compatible = "allwinner,sun9i-a80-display-backend",
1055 .name = "sun4i-backend",
1061 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");