Lines Matching +full:jz4780 +full:- +full:dma
1 // SPDX-License-Identifier: GPL-2.0
7 #include "ingenic-drm.h"
12 #include <linux/dma-mapping.h>
14 #include <linux/media-bus-format.h>
54 /* extended hw descriptor for jz4780 */
88 * f0 (aka. foreground0) can be overlayed. Z-order is fixed in
147 priv_state = drm_atomic_get_private_obj_state(state, &priv->private_obj); in ingenic_drm_get_priv_state()
159 priv_state = drm_atomic_get_new_private_obj_state(state, &priv->private_obj); in ingenic_drm_get_new_priv_state()
210 return priv->dma_hwdescs_phys + offset; in dma_hwdesc_addr()
221 mutex_lock(&priv->clk_mutex); in ingenic_drm_update_pixclk()
222 priv->update_clk_rate = true; in ingenic_drm_update_pixclk()
223 drm_crtc_wait_one_vblank(&priv->crtc); in ingenic_drm_update_pixclk()
226 mutex_unlock(&priv->clk_mutex); in ingenic_drm_update_pixclk()
234 struct ingenic_drm *priv = drm_device_get_priv(bridge->dev); in ingenic_drm_bridge_atomic_enable()
236 regmap_write(priv->map, JZ_REG_LCD_STATE, 0); in ingenic_drm_bridge_atomic_enable()
238 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, in ingenic_drm_bridge_atomic_enable()
254 /* Set addresses of our DMA descriptor chains */ in ingenic_drm_crtc_atomic_enable()
255 next_id = priv_state->use_palette ? HWDESC_PALETTE : 0; in ingenic_drm_crtc_atomic_enable()
256 regmap_write(priv->map, JZ_REG_LCD_DA0, dma_hwdesc_addr(priv, next_id)); in ingenic_drm_crtc_atomic_enable()
257 regmap_write(priv->map, JZ_REG_LCD_DA1, dma_hwdesc_addr(priv, 1)); in ingenic_drm_crtc_atomic_enable()
265 struct ingenic_drm *priv = drm_device_get_priv(bridge->dev); in ingenic_drm_bridge_atomic_disable()
268 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, in ingenic_drm_bridge_atomic_disable()
271 regmap_read_poll_timeout(priv->map, JZ_REG_LCD_STATE, var, in ingenic_drm_bridge_atomic_disable()
287 vpe = mode->crtc_vsync_end - mode->crtc_vsync_start; in ingenic_drm_crtc_update_timings()
288 vds = mode->crtc_vtotal - mode->crtc_vsync_start; in ingenic_drm_crtc_update_timings()
289 vde = vds + mode->crtc_vdisplay; in ingenic_drm_crtc_update_timings()
290 vt = vde + mode->crtc_vsync_start - mode->crtc_vdisplay; in ingenic_drm_crtc_update_timings()
292 hpe = mode->crtc_hsync_end - mode->crtc_hsync_start; in ingenic_drm_crtc_update_timings()
293 hds = mode->crtc_htotal - mode->crtc_hsync_start; in ingenic_drm_crtc_update_timings()
294 hde = hds + mode->crtc_hdisplay; in ingenic_drm_crtc_update_timings()
295 ht = hde + mode->crtc_hsync_start - mode->crtc_hdisplay; in ingenic_drm_crtc_update_timings()
297 regmap_write(priv->map, JZ_REG_LCD_VSYNC, in ingenic_drm_crtc_update_timings()
301 regmap_write(priv->map, JZ_REG_LCD_HSYNC, in ingenic_drm_crtc_update_timings()
305 regmap_write(priv->map, JZ_REG_LCD_VAT, in ingenic_drm_crtc_update_timings()
309 regmap_write(priv->map, JZ_REG_LCD_DAH, in ingenic_drm_crtc_update_timings()
312 regmap_write(priv->map, JZ_REG_LCD_DAV, in ingenic_drm_crtc_update_timings()
316 if (priv->panel_is_sharp) { in ingenic_drm_crtc_update_timings()
317 regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1)); in ingenic_drm_crtc_update_timings()
318 regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1)); in ingenic_drm_crtc_update_timings()
319 regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1)); in ingenic_drm_crtc_update_timings()
320 regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16); in ingenic_drm_crtc_update_timings()
323 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, in ingenic_drm_crtc_update_timings()
325 JZ_LCD_CTRL_OFUP | priv->soc_info->max_burst); in ingenic_drm_crtc_update_timings()
328 * IPU restart - specify how much time the LCDC will wait before in ingenic_drm_crtc_update_timings()
332 regmap_write(priv->map, JZ_REG_LCD_IPUR, JZ_LCD_IPUR_IPUREN | in ingenic_drm_crtc_update_timings()
344 if (crtc_state->gamma_lut && in ingenic_drm_crtc_atomic_check()
345 drm_color_lut_size(crtc_state->gamma_lut) != ARRAY_SIZE(priv->dma_hwdescs->palette)) { in ingenic_drm_crtc_atomic_check()
346 dev_dbg(priv->dev, "Invalid palette size\n"); in ingenic_drm_crtc_atomic_check()
347 return -EINVAL; in ingenic_drm_crtc_atomic_check()
350 if (drm_atomic_crtc_needs_modeset(crtc_state) && priv->soc_info->has_osd) { in ingenic_drm_crtc_atomic_check()
351 f1_state = drm_atomic_get_plane_state(crtc_state->state, in ingenic_drm_crtc_atomic_check()
352 &priv->f1); in ingenic_drm_crtc_atomic_check()
356 f0_state = drm_atomic_get_plane_state(crtc_state->state, in ingenic_drm_crtc_atomic_check()
357 &priv->f0); in ingenic_drm_crtc_atomic_check()
361 if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && priv->ipu_plane) { in ingenic_drm_crtc_atomic_check()
362 ipu_state = drm_atomic_get_plane_state(crtc_state->state, in ingenic_drm_crtc_atomic_check()
363 priv->ipu_plane); in ingenic_drm_crtc_atomic_check()
368 if (f1_state->fb && ipu_state->fb) { in ingenic_drm_crtc_atomic_check()
369 dev_dbg(priv->dev, "Cannot enable both F1 and IPU\n"); in ingenic_drm_crtc_atomic_check()
370 return -EINVAL; in ingenic_drm_crtc_atomic_check()
375 priv->no_vblank = !f1_state->fb && !f0_state->fb && in ingenic_drm_crtc_atomic_check()
376 !(ipu_state && ipu_state->fb); in ingenic_drm_crtc_atomic_check()
388 if (mode->hdisplay > priv->soc_info->max_width) in ingenic_drm_crtc_mode_valid()
390 if (mode->vdisplay > priv->soc_info->max_height) in ingenic_drm_crtc_mode_valid()
393 rate = clk_round_rate(priv->pix_clk, mode->clock * 1000); in ingenic_drm_crtc_mode_valid()
408 if (priv->soc_info->has_osd && in ingenic_drm_crtc_atomic_begin()
412 * plane; otherwise use regular DMA. in ingenic_drm_crtc_atomic_begin()
414 if (priv->ipu_plane && priv->ipu_plane->state->fb) in ingenic_drm_crtc_atomic_begin()
417 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL, in ingenic_drm_crtc_atomic_begin()
428 struct drm_pending_vblank_event *event = crtc_state->event; in ingenic_drm_crtc_atomic_flush()
431 ingenic_drm_crtc_update_timings(priv, &crtc_state->adjusted_mode); in ingenic_drm_crtc_atomic_flush()
432 priv->update_clk_rate = true; in ingenic_drm_crtc_atomic_flush()
435 if (priv->update_clk_rate) { in ingenic_drm_crtc_atomic_flush()
436 mutex_lock(&priv->clk_mutex); in ingenic_drm_crtc_atomic_flush()
437 clk_set_rate(priv->pix_clk, in ingenic_drm_crtc_atomic_flush()
438 crtc_state->adjusted_mode.crtc_clock * 1000); in ingenic_drm_crtc_atomic_flush()
439 priv->update_clk_rate = false; in ingenic_drm_crtc_atomic_flush()
440 mutex_unlock(&priv->clk_mutex); in ingenic_drm_crtc_atomic_flush()
444 crtc_state->event = NULL; in ingenic_drm_crtc_atomic_flush()
446 spin_lock_irq(&crtc->dev->event_lock); in ingenic_drm_crtc_atomic_flush()
451 spin_unlock_irq(&crtc->dev->event_lock); in ingenic_drm_crtc_atomic_flush()
462 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); in ingenic_drm_plane_atomic_check()
465 struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc; in ingenic_drm_plane_atomic_check()
471 if (priv->soc_info->plane_f0_not_working && plane == &priv->f0) in ingenic_drm_plane_atomic_check()
472 return -EINVAL; in ingenic_drm_plane_atomic_check()
477 return -EINVAL; in ingenic_drm_plane_atomic_check()
486 priv->soc_info->has_osd, in ingenic_drm_plane_atomic_check()
493 * Note that state->src_* are in 16.16 fixed-point format. in ingenic_drm_plane_atomic_check()
495 if (!priv->soc_info->has_osd && in ingenic_drm_plane_atomic_check()
496 (new_plane_state->src_x != 0 || in ingenic_drm_plane_atomic_check()
497 (new_plane_state->src_w >> 16) != new_plane_state->crtc_w || in ingenic_drm_plane_atomic_check()
498 (new_plane_state->src_h >> 16) != new_plane_state->crtc_h)) in ingenic_drm_plane_atomic_check()
499 return -EINVAL; in ingenic_drm_plane_atomic_check()
501 priv_state->use_palette = new_plane_state->fb && in ingenic_drm_plane_atomic_check()
502 new_plane_state->fb->format->format == DRM_FORMAT_C8; in ingenic_drm_plane_atomic_check()
508 if (priv->soc_info->has_osd && in ingenic_drm_plane_atomic_check()
509 (!old_plane_state->fb || !new_plane_state->fb || in ingenic_drm_plane_atomic_check()
510 old_plane_state->crtc_x != new_plane_state->crtc_x || in ingenic_drm_plane_atomic_check()
511 old_plane_state->crtc_y != new_plane_state->crtc_y || in ingenic_drm_plane_atomic_check()
512 old_plane_state->crtc_w != new_plane_state->crtc_w || in ingenic_drm_plane_atomic_check()
513 old_plane_state->crtc_h != new_plane_state->crtc_h || in ingenic_drm_plane_atomic_check()
514 old_plane_state->fb->format->format != new_plane_state->fb->format->format)) in ingenic_drm_plane_atomic_check()
515 crtc_state->mode_changed = true; in ingenic_drm_plane_atomic_check()
517 if (priv->soc_info->map_noncoherent) in ingenic_drm_plane_atomic_check()
528 if (priv->soc_info->has_osd) { in ingenic_drm_plane_enable()
529 if (plane != &priv->f0) in ingenic_drm_plane_enable()
534 regmap_set_bits(priv->map, JZ_REG_LCD_OSDC, en_bit); in ingenic_drm_plane_enable()
543 if (priv->soc_info->has_osd) { in ingenic_drm_plane_disable()
544 if (plane != &priv->f0) in ingenic_drm_plane_disable()
549 regmap_clear_bits(priv->map, JZ_REG_LCD_OSDC, en_bit); in ingenic_drm_plane_disable()
556 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); in ingenic_drm_plane_atomic_disable()
558 ingenic_drm_plane_disable(priv->dev, plane); in ingenic_drm_plane_atomic_disable()
565 struct drm_plane_state *state = plane->state; in ingenic_drm_plane_config()
571 if (priv->soc_info->has_osd && plane != &priv->f0) { in ingenic_drm_plane_config()
590 regmap_update_bits(priv->map, JZ_REG_LCD_OSDCTRL, in ingenic_drm_plane_config()
614 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, in ingenic_drm_plane_config()
618 if (priv->soc_info->has_osd) { in ingenic_drm_plane_config()
619 if (plane != &priv->f0) { in ingenic_drm_plane_config()
627 regmap_write(priv->map, xy_reg, in ingenic_drm_plane_config()
628 state->crtc_x << JZ_LCD_XYP01_XPOS_LSB | in ingenic_drm_plane_config()
629 state->crtc_y << JZ_LCD_XYP01_YPOS_LSB); in ingenic_drm_plane_config()
630 regmap_write(priv->map, size_reg, in ingenic_drm_plane_config()
631 state->crtc_w << JZ_LCD_SIZE01_WIDTH_LSB | in ingenic_drm_plane_config()
632 state->crtc_h << JZ_LCD_SIZE01_HEIGHT_LSB); in ingenic_drm_plane_config()
640 return priv->soc_info->map_noncoherent; in ingenic_drm_map_noncoherent()
648 for (i = 0; i < ARRAY_SIZE(priv->dma_hwdescs->palette); i++) { in ingenic_drm_update_palette()
653 priv->dma_hwdescs->palette[i] = color; in ingenic_drm_update_palette()
660 struct ingenic_drm *priv = drm_device_get_priv(plane->dev); in ingenic_drm_plane_atomic_update()
670 if (newstate && newstate->fb) { in ingenic_drm_plane_atomic_update()
671 if (priv->soc_info->map_noncoherent) in ingenic_drm_plane_atomic_update()
672 drm_fb_dma_sync_non_coherent(&priv->drm, oldstate, newstate); in ingenic_drm_plane_atomic_update()
674 crtc_state = newstate->crtc->state; in ingenic_drm_plane_atomic_update()
675 plane_id = !!(priv->soc_info->has_osd && plane != &priv->f0); in ingenic_drm_plane_atomic_update()
677 addr = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0); in ingenic_drm_plane_atomic_update()
678 width = newstate->src_w >> 16; in ingenic_drm_plane_atomic_update()
679 height = newstate->src_h >> 16; in ingenic_drm_plane_atomic_update()
680 cpp = newstate->fb->format->cpp[0]; in ingenic_drm_plane_atomic_update()
683 next_id = (priv_state && priv_state->use_palette) ? HWDESC_PALETTE : plane_id; in ingenic_drm_plane_atomic_update()
685 hwdesc = &priv->dma_hwdescs->hwdesc[plane_id]; in ingenic_drm_plane_atomic_update()
686 hwdesc->addr = addr; in ingenic_drm_plane_atomic_update()
687 hwdesc->cmd = JZ_LCD_CMD_EOF_IRQ | (width * height * cpp / 4); in ingenic_drm_plane_atomic_update()
688 hwdesc->next = dma_hwdesc_addr(priv, next_id); in ingenic_drm_plane_atomic_update()
690 if (priv->soc_info->use_extended_hwdesc) { in ingenic_drm_plane_atomic_update()
691 hwdesc->cmd |= JZ_LCD_CMD_FRM_ENABLE; in ingenic_drm_plane_atomic_update()
693 /* Extended 8-byte descriptor */ in ingenic_drm_plane_atomic_update()
694 hwdesc->cpos = 0; in ingenic_drm_plane_atomic_update()
695 hwdesc->offsize = 0; in ingenic_drm_plane_atomic_update()
696 hwdesc->pagewidth = 0; in ingenic_drm_plane_atomic_update()
698 switch (newstate->fb->format->format) { in ingenic_drm_plane_atomic_update()
700 hwdesc->cpos |= JZ_LCD_CPOS_RGB555; in ingenic_drm_plane_atomic_update()
703 hwdesc->cpos |= JZ_LCD_CPOS_BPP_15_16; in ingenic_drm_plane_atomic_update()
706 hwdesc->cpos |= JZ_LCD_CPOS_BPP_18_24; in ingenic_drm_plane_atomic_update()
709 hwdesc->cpos |= (JZ_LCD_CPOS_COEFFICIENT_1 << in ingenic_drm_plane_atomic_update()
711 hwdesc->dessize = in ingenic_drm_plane_atomic_update()
713 FIELD_PREP(JZ_LCD_DESSIZE_HEIGHT_MASK, height - 1) | in ingenic_drm_plane_atomic_update()
714 FIELD_PREP(JZ_LCD_DESSIZE_WIDTH_MASK, width - 1); in ingenic_drm_plane_atomic_update()
718 fourcc = newstate->fb->format->format; in ingenic_drm_plane_atomic_update()
720 ingenic_drm_plane_config(priv->dev, plane, fourcc); in ingenic_drm_plane_atomic_update()
722 crtc_state->color_mgmt_changed = fourcc == DRM_FORMAT_C8; in ingenic_drm_plane_atomic_update()
725 if (crtc_state->color_mgmt_changed) in ingenic_drm_plane_atomic_update()
726 ingenic_drm_update_palette(priv, crtc_state->gamma_lut->data); in ingenic_drm_plane_atomic_update()
734 struct ingenic_drm *priv = drm_device_get_priv(encoder->dev); in ingenic_drm_encoder_atomic_mode_set()
735 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in ingenic_drm_encoder_atomic_mode_set()
739 priv->panel_is_sharp = bridge->bus_cfg.flags & DRM_BUS_FLAG_SHARP_SIGNALS; in ingenic_drm_encoder_atomic_mode_set()
741 if (priv->panel_is_sharp) { in ingenic_drm_encoder_atomic_mode_set()
748 if (priv->soc_info->use_extended_hwdesc) in ingenic_drm_encoder_atomic_mode_set()
751 if (mode->flags & DRM_MODE_FLAG_NHSYNC) in ingenic_drm_encoder_atomic_mode_set()
753 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in ingenic_drm_encoder_atomic_mode_set()
755 if (bridge->bus_cfg.flags & DRM_BUS_FLAG_DE_LOW) in ingenic_drm_encoder_atomic_mode_set()
757 if (bridge->bus_cfg.flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) in ingenic_drm_encoder_atomic_mode_set()
760 if (!priv->panel_is_sharp) { in ingenic_drm_encoder_atomic_mode_set()
761 if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) { in ingenic_drm_encoder_atomic_mode_set()
762 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in ingenic_drm_encoder_atomic_mode_set()
767 switch (bridge->bus_cfg.format) { in ingenic_drm_encoder_atomic_mode_set()
789 regmap_write(priv->map, JZ_REG_LCD_CFG, cfg); in ingenic_drm_encoder_atomic_mode_set()
790 regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg); in ingenic_drm_encoder_atomic_mode_set()
796 struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); in ingenic_drm_bridge_attach()
798 return drm_bridge_attach(bridge->encoder, ib->next_bridge, in ingenic_drm_bridge_attach()
799 &ib->bridge, flags); in ingenic_drm_bridge_attach()
807 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in ingenic_drm_bridge_atomic_check()
808 struct ingenic_drm_bridge *ib = to_ingenic_drm_bridge(bridge->encoder); in ingenic_drm_bridge_atomic_check()
810 ib->bus_cfg = bridge_state->output_bus_cfg; in ingenic_drm_bridge_atomic_check()
812 if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) in ingenic_drm_bridge_atomic_check()
815 switch (bridge_state->output_bus_cfg.format) { in ingenic_drm_bridge_atomic_check()
819 * The LCD controller expects timing values in dot-clock ticks, in ingenic_drm_bridge_atomic_check()
820 * which is 3x the timing values in pixels when using a 3x8-bit in ingenic_drm_bridge_atomic_check()
824 mode->crtc_clock = mode->clock * 3; in ingenic_drm_bridge_atomic_check()
825 mode->crtc_hsync_start = mode->hsync_start * 3 - mode->hdisplay * 2; in ingenic_drm_bridge_atomic_check()
826 mode->crtc_hsync_end = mode->hsync_end * 3 - mode->hdisplay * 2; in ingenic_drm_bridge_atomic_check()
827 mode->crtc_hdisplay = mode->hdisplay; in ingenic_drm_bridge_atomic_check()
828 mode->crtc_htotal = mode->htotal * 3 - mode->hdisplay * 2; in ingenic_drm_bridge_atomic_check()
835 return -EINVAL; in ingenic_drm_bridge_atomic_check()
870 regmap_read(priv->map, JZ_REG_LCD_STATE, &state); in ingenic_drm_irq_handler()
872 regmap_update_bits(priv->map, JZ_REG_LCD_STATE, in ingenic_drm_irq_handler()
876 drm_crtc_handle_vblank(&priv->crtc); in ingenic_drm_irq_handler()
885 if (priv->no_vblank) in ingenic_drm_enable_vblank()
886 return -EINVAL; in ingenic_drm_enable_vblank()
888 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, in ingenic_drm_enable_vblank()
898 regmap_update_bits(priv->map, JZ_REG_LCD_CTRL, JZ_LCD_CTRL_EOF_IRQ, 0); in ingenic_drm_disable_vblank()
907 if (priv->soc_info->map_noncoherent) in ingenic_drm_gem_fb_create()
921 return ERR_PTR(-ENOMEM); in ingenic_drm_gem_create_object()
923 obj->map_noncoherent = priv->soc_info->map_noncoherent; in ingenic_drm_gem_create_object()
925 return &obj->base; in ingenic_drm_gem_create_object()
931 struct ingenic_drm_private_state *state = to_ingenic_drm_priv_state(obj->state); in ingenic_drm_duplicate_state()
937 __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); in ingenic_drm_duplicate_state()
939 return &state->base; in ingenic_drm_duplicate_state()
954 .name = "ingenic-drm",
1039 component_unbind_all(priv->dev, &priv->drm); in ingenic_drm_unbind_all()
1051 struct ingenic_dma_hwdesc *desc = &priv->dma_hwdescs->hwdesc[hwdesc]; in ingenic_drm_configure_hwdesc()
1053 desc->next = dma_hwdesc_addr(priv, next_hwdesc); in ingenic_drm_configure_hwdesc()
1054 desc->id = id; in ingenic_drm_configure_hwdesc()
1063 desc = &priv->dma_hwdescs->hwdesc[HWDESC_PALETTE]; in ingenic_drm_configure_hwdesc_palette()
1064 desc->addr = priv->dma_hwdescs_phys in ingenic_drm_configure_hwdesc_palette()
1066 desc->cmd = JZ_LCD_CMD_ENABLE_PAL in ingenic_drm_configure_hwdesc_palette()
1067 | (sizeof(priv->dma_hwdescs->palette) / 4); in ingenic_drm_configure_hwdesc_palette()
1106 return -EINVAL; in ingenic_drm_bind()
1112 if (ret && ret != -ENODEV) in ingenic_drm_bind()
1127 priv->soc_info = soc_info; in ingenic_drm_bind()
1128 priv->dev = dev; in ingenic_drm_bind()
1129 drm = &priv->drm; in ingenic_drm_bind()
1137 drm->mode_config.min_width = 0; in ingenic_drm_bind()
1138 drm->mode_config.min_height = 0; in ingenic_drm_bind()
1139 drm->mode_config.max_width = soc_info->max_width; in ingenic_drm_bind()
1140 drm->mode_config.max_height = 4095; in ingenic_drm_bind()
1141 drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; in ingenic_drm_bind()
1142 drm->mode_config.helper_private = &ingenic_drm_mode_config_helpers; in ingenic_drm_bind()
1152 regmap_config.max_register = res->end - res->start; in ingenic_drm_bind()
1153 priv->map = devm_regmap_init_mmio(dev, base, in ingenic_drm_bind()
1155 if (IS_ERR(priv->map)) { in ingenic_drm_bind()
1157 ret = PTR_ERR(priv->map); in ingenic_drm_bind()
1167 if (soc_info->needs_dev_clk) { in ingenic_drm_bind()
1168 priv->lcd_clk = devm_clk_get(dev, "lcd"); in ingenic_drm_bind()
1169 if (IS_ERR(priv->lcd_clk)) { in ingenic_drm_bind()
1171 ret = PTR_ERR(priv->lcd_clk); in ingenic_drm_bind()
1176 priv->pix_clk = devm_clk_get(dev, "lcd_pclk"); in ingenic_drm_bind()
1177 if (IS_ERR(priv->pix_clk)) { in ingenic_drm_bind()
1179 ret = PTR_ERR(priv->pix_clk); in ingenic_drm_bind()
1183 priv->dma_hwdescs = dmam_alloc_coherent(dev, in ingenic_drm_bind()
1184 sizeof(*priv->dma_hwdescs), in ingenic_drm_bind()
1185 &priv->dma_hwdescs_phys, in ingenic_drm_bind()
1187 if (!priv->dma_hwdescs) { in ingenic_drm_bind()
1188 ret = -ENOMEM; in ingenic_drm_bind()
1192 /* Configure DMA hwdesc for foreground0 plane */ in ingenic_drm_bind()
1195 /* Configure DMA hwdesc for foreground1 plane */ in ingenic_drm_bind()
1198 /* Configure DMA hwdesc for palette */ in ingenic_drm_bind()
1201 primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0; in ingenic_drm_bind()
1207 priv->soc_info->formats_f1, in ingenic_drm_bind()
1208 priv->soc_info->num_formats_f1, in ingenic_drm_bind()
1215 if (soc_info->map_noncoherent) in ingenic_drm_bind()
1216 drm_plane_enable_fb_damage_clips(&priv->f1); in ingenic_drm_bind()
1218 drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); in ingenic_drm_bind()
1220 ret = drm_crtc_init_with_planes(drm, &priv->crtc, primary, in ingenic_drm_bind()
1227 drm_crtc_enable_color_mgmt(&priv->crtc, 0, false, in ingenic_drm_bind()
1228 ARRAY_SIZE(priv->dma_hwdescs->palette)); in ingenic_drm_bind()
1230 if (soc_info->has_osd) { in ingenic_drm_bind()
1231 drm_plane_helper_add(&priv->f0, in ingenic_drm_bind()
1234 ret = drm_universal_plane_init(drm, &priv->f0, 1, in ingenic_drm_bind()
1236 priv->soc_info->formats_f0, in ingenic_drm_bind()
1237 priv->soc_info->num_formats_f0, in ingenic_drm_bind()
1246 if (soc_info->map_noncoherent) in ingenic_drm_bind()
1247 drm_plane_enable_fb_damage_clips(&priv->f0); in ingenic_drm_bind()
1252 if (ret != -EPROBE_DEFER) in ingenic_drm_bind()
1261 priv->ipu_plane = drm_plane_from_index(drm, 2); in ingenic_drm_bind()
1262 if (!priv->ipu_plane) { in ingenic_drm_bind()
1264 ret = -EINVAL; in ingenic_drm_bind()
1271 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, i, &panel, &bridge); in ingenic_drm_bind()
1273 if (ret == -ENODEV) in ingenic_drm_bind()
1275 if (ret != -EPROBE_DEFER) in ingenic_drm_bind()
1292 encoder = &ib->encoder; in ingenic_drm_bind()
1293 encoder->possible_crtcs = drm_crtc_mask(&priv->crtc); in ingenic_drm_bind()
1297 ib->bridge.funcs = &ingenic_drm_bridge_funcs; in ingenic_drm_bind()
1298 ib->next_bridge = bridge; in ingenic_drm_bind()
1300 ret = drm_bridge_attach(encoder, &ib->bridge, NULL, in ingenic_drm_bind()
1322 encoder->possible_clones = clone_mask; in ingenic_drm_bind()
1325 ret = devm_request_irq(dev, irq, ingenic_drm_irq_handler, 0, drm->driver->name, drm); in ingenic_drm_bind()
1339 ret = clk_prepare_enable(priv->pix_clk); in ingenic_drm_bind()
1345 if (priv->lcd_clk) { in ingenic_drm_bind()
1346 parent_clk = clk_get_parent(priv->lcd_clk); in ingenic_drm_bind()
1354 ret = clk_set_rate(priv->lcd_clk, parent_rate); in ingenic_drm_bind()
1360 ret = clk_prepare_enable(priv->lcd_clk); in ingenic_drm_bind()
1368 if (soc_info->has_osd) in ingenic_drm_bind()
1370 if (soc_info->has_alpha) in ingenic_drm_bind()
1372 regmap_write(priv->map, JZ_REG_LCD_OSDC, osdc); in ingenic_drm_bind()
1374 mutex_init(&priv->clk_mutex); in ingenic_drm_bind()
1375 priv->clock_nb.notifier_call = ingenic_drm_update_pixclk; in ingenic_drm_bind()
1377 parent_clk = clk_get_parent(priv->pix_clk); in ingenic_drm_bind()
1378 ret = clk_notifier_register(parent_clk, &priv->clock_nb); in ingenic_drm_bind()
1386 ret = -ENOMEM; in ingenic_drm_bind()
1390 drm_atomic_private_obj_init(drm, &priv->private_obj, &private_state->base, in ingenic_drm_bind()
1394 &priv->private_obj); in ingenic_drm_bind()
1411 clk_notifier_unregister(parent_clk, &priv->clock_nb); in ingenic_drm_bind()
1413 if (priv->lcd_clk) in ingenic_drm_bind()
1414 clk_disable_unprepare(priv->lcd_clk); in ingenic_drm_bind()
1416 clk_disable_unprepare(priv->pix_clk); in ingenic_drm_bind()
1430 struct clk *parent_clk = clk_get_parent(priv->pix_clk); in ingenic_drm_unbind()
1432 clk_notifier_unregister(parent_clk, &priv->clock_nb); in ingenic_drm_unbind()
1433 if (priv->lcd_clk) in ingenic_drm_unbind()
1434 clk_disable_unprepare(priv->lcd_clk); in ingenic_drm_unbind()
1435 clk_disable_unprepare(priv->pix_clk); in ingenic_drm_unbind()
1437 drm_dev_unregister(&priv->drm); in ingenic_drm_unbind()
1438 drm_atomic_helper_shutdown(&priv->drm); in ingenic_drm_unbind()
1449 struct device *dev = &pdev->dev; in ingenic_drm_probe()
1457 np = of_graph_get_remote_node(dev->of_node, 8, 0); in ingenic_drm_probe()
1469 struct device *dev = &pdev->dev; in ingenic_drm_remove()
1482 drm_atomic_helper_shutdown(&priv->drm); in ingenic_drm_shutdown()
1489 return drm_mode_config_helper_suspend(&priv->drm); in ingenic_drm_suspend()
1496 return drm_mode_config_helper_resume(&priv->drm); in ingenic_drm_resume()
1618 { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
1619 { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
1620 { .compatible = "ingenic,jz4760-lcd", .data = &jz4760_soc_info },
1621 { .compatible = "ingenic,jz4760b-lcd", .data = &jz4760b_soc_info },
1622 { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },
1623 { .compatible = "ingenic,jz4780-lcd", .data = &jz4780_soc_info },
1630 .name = "ingenic-drm",
1644 return -ENODEV; in ingenic_drm_init()