Lines Matching +full:touch +full:- +full:overlay

1 // SPDX-License-Identifier: GPL-2.0-only
10 #include <linux/dma-mapping.h>
44 stats->frames = 0;
45 stats->vblank = 0;
46 stats->underflow = 0;
47 stats->overflow = 0;
66 offset = 0x000 + (offset - 0x500);
67 return plane->offset + offset;
71 offset = 0x180 + (offset - 0x700);
72 return plane->offset + offset;
76 offset = 0x1c0 + (offset - 0x800);
77 return plane->offset + offset;
80 dev_WARN(plane->dc->dev, "invalid offset: %x\n", offset);
82 return plane->offset + offset;
88 return tegra_dc_readl(plane->dc, tegra_plane_offset(plane, offset));
94 tegra_dc_writel(plane->dc, value, tegra_plane_offset(plane, offset));
99 struct device_node *np = dc->dev->of_node;
104 if (it.node == dev->of_node)
111 * Double-buffered registers have two copies: ASSEMBLY and ACTIVE. When the
116 * Triple-buffered registers have three copies: ASSEMBLY, ARM and ACTIVE. The
153 outf.full = max_t(u32, outf.full - dfixed_const(1), dfixed_const(1));
154 inf.full -= dfixed_const(1);
182 /* disable blending for non-overlapping case */
186 state = to_tegra_plane_state(plane->base.state);
188 if (state->opaque) {
190 * Since custom fix-weight blending isn't utilized and weight
207 switch (state->base.normalized_zpos) {
209 if (state->blending[0].alpha &&
210 state->blending[1].alpha)
232 if (state->blending[i].alpha &&
233 state->blending[i].top)
237 switch (state->base.normalized_zpos) {
239 if (state->blending[0].alpha &&
240 state->blending[1].alpha)
250 if (state->blending[0].alpha &&
251 state->blending[0].top)
254 if (state->blending[1].alpha &&
255 state->blending[1].top)
261 switch (state->base.normalized_zpos) {
274 if (!state->blending[0].top && state->blending[1].top) {
310 value = K2(255) | K1(255) | WINDOW_LAYER_DEPTH(255 - window->zpos);
318 struct tegra_dc *dc = plane->dc;
320 if (window->src.w == window->dst.w)
323 if (plane->index == 0 && dc->soc->has_win_a_without_filters)
333 struct tegra_dc *dc = plane->dc;
335 if (window->src.h == window->dst.h)
338 if (plane->index == 0 && dc->soc->has_win_a_without_filters)
341 if (plane->index == 2 && dc->soc->has_win_c_without_vert_filter)
351 struct tegra_dc *dc = plane->dc;
360 yuv = tegra_plane_format_is_yuv(window->format, &planes, NULL);
362 bpp = window->bits_per_pixel / 8;
366 tegra_plane_writel(plane, window->format, DC_WIN_COLOR_DEPTH);
367 tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP);
369 value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x);
372 value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w);
375 h_offset = window->src.x * bpp;
376 v_offset = window->src.y;
377 h_size = window->src.w * bpp;
378 v_size = window->src.h;
380 if (window->reflect_x)
381 h_offset += (window->src.w - 1) * bpp;
383 if (window->reflect_y)
384 v_offset += window->src.h - 1;
396 h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
397 v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp);
402 h_dda = compute_initial_dda(window->src.x);
403 v_dda = compute_initial_dda(window->src.y);
411 tegra_plane_writel(plane, window->base[0], DC_WINBUF_START_ADDR);
414 tegra_plane_writel(plane, window->base[1], DC_WINBUF_START_ADDR_U);
417 tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);
419 value = window->stride[1] << 16 | window->stride[0];
422 tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
428 if (dc->soc->supports_block_linear) {
429 unsigned long height = window->tiling.value;
431 switch (window->tiling.mode) {
448 switch (window->tiling.mode) {
461 * No need to handle this here because ->atomic_check
484 } else if (window->bits_per_pixel < 24) {
488 if (window->reflect_x)
491 if (window->reflect_y)
496 * Enable horizontal 6-tap filter and set filtering
523 * Enable vertical 2-tap filter and set filtering
526 for (i = 0, k = 128; i < 16; i++, k -= 8)
534 if (dc->soc->has_legacy_blending)
547 /* non-native formats */
627 unsigned int rotation = new_plane_state->rotation;
628 struct tegra_bo_tiling *tiling = &plane_state->tiling;
630 struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);
633 plane_state->peak_memory_bandwidth = 0;
634 plane_state->avg_memory_bandwidth = 0;
637 if (!new_plane_state->crtc) {
638 plane_state->total_peak_memory_bandwidth = 0;
642 err = tegra_plane_format(new_plane_state->fb->format->format,
643 &plane_state->format,
644 &plane_state->swap);
654 if (dc->soc->has_legacy_blending) {
660 err = tegra_fb_get_tiling(new_plane_state->fb, tiling);
664 if (tiling->mode == TEGRA_BO_TILING_MODE_BLOCK &&
665 !dc->soc->supports_block_linear) {
667 return -EINVAL;
676 if (tegra_fb_is_bottom_up(new_plane_state->fb))
682 plane_state->reflect_x = true;
684 plane_state->reflect_x = false;
687 plane_state->reflect_y = true;
689 plane_state->reflect_y = false;
696 if (new_plane_state->fb->format->num_planes > 2) {
697 if (new_plane_state->fb->pitches[2] != new_plane_state->fb->pitches[1]) {
698 DRM_ERROR("unsupported UV-plane configuration\n");
699 return -EINVAL;
719 if (!old_state || !old_state->crtc)
733 struct drm_framebuffer *fb = new_state->fb;
739 if (!new_state->crtc || !new_state->fb)
742 if (!new_state->visible)
746 window.src.x = new_state->src.x1 >> 16;
747 window.src.y = new_state->src.y1 >> 16;
748 window.src.w = drm_rect_width(&new_state->src) >> 16;
749 window.src.h = drm_rect_height(&new_state->src) >> 16;
750 window.dst.x = new_state->dst.x1;
751 window.dst.y = new_state->dst.y1;
752 window.dst.w = drm_rect_width(&new_state->dst);
753 window.dst.h = drm_rect_height(&new_state->dst);
754 window.bits_per_pixel = fb->format->cpp[0] * 8;
755 window.reflect_x = tegra_plane_state->reflect_x;
756 window.reflect_y = tegra_plane_state->reflect_y;
759 window.zpos = new_state->normalized_zpos;
760 window.tiling = tegra_plane_state->tiling;
761 window.format = tegra_plane_state->format;
762 window.swap = tegra_plane_state->swap;
764 for (i = 0; i < fb->format->num_planes; i++) {
765 window.base[i] = tegra_plane_state->iova[i] + fb->offsets[i];
770 * function, so it's safe to ignore the V-plane pitch here.
773 window.stride[i] = fb->pitches[i];
801 return 1 << drm->mode_config.num_crtc;
817 return ERR_PTR(-ENOMEM);
820 plane->offset = 0xa00;
821 plane->index = 0;
822 plane->dc = dc;
824 num_formats = dc->soc->num_primary_formats;
825 formats = dc->soc->primary_formats;
826 modifiers = dc->soc->modifiers;
834 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
842 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
843 drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
845 err = drm_plane_create_rotation_property(&plane->base,
852 dev_err(dc->dev, "failed to create rotation property: %d\n",
855 return &plane->base;
875 plane_state->peak_memory_bandwidth = 0;
876 plane_state->avg_memory_bandwidth = 0;
879 if (!new_plane_state->crtc) {
880 plane_state->total_peak_memory_bandwidth = 0;
885 if ((new_plane_state->src_w >> 16 != new_plane_state->crtc_w) ||
886 (new_plane_state->src_h >> 16 != new_plane_state->crtc_h))
887 return -EINVAL;
890 if (new_plane_state->src_w != new_plane_state->src_h)
891 return -EINVAL;
893 if (new_plane_state->crtc_w != 32 && new_plane_state->crtc_w != 64 &&
894 new_plane_state->crtc_w != 128 && new_plane_state->crtc_w != 256)
895 return -EINVAL;
908 struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
909 struct tegra_drm *tegra = plane->dev->dev_private;
911 u64 dma_mask = *dc->dev->dma_mask;
917 if (!new_state->crtc || !new_state->fb)
924 if (!dc->soc->has_nvdisplay)
927 switch (new_state->crtc_w) {
946 new_state->crtc_w, new_state->crtc_h);
950 value |= (tegra_plane_state->iova[0] >> 10) & 0x3fffff;
954 value = (tegra_plane_state->iova[0] >> 32) & (dma_mask >> 32);
967 if (dc->soc->has_nvdisplay)
978 if (dc->soc->has_nvdisplay) {
981 x = new_state->dst.x1;
982 y = new_state->dst.y1;
984 drm_rect_fp_to_int(&src, &new_state->src);
986 value = (src.y1 & tegra->vmask) << 16 | (src.x1 & tegra->hmask);
989 value = (drm_rect_height(&src) & tegra->vmask) << 16 |
990 (drm_rect_width(&src) & tegra->hmask);
993 x = new_state->crtc_x;
994 y = new_state->crtc_y;
998 value = ((y & tegra->vmask) << 16) | (x & tegra->hmask);
1019 if (!old_state || !old_state->crtc)
1022 dc = to_tegra_dc(old_state->crtc);
1037 crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
1039 return -EINVAL;
1041 if (!crtc_state->active)
1042 return -EINVAL;
1044 if (plane->state->crtc != new_state->crtc ||
1045 plane->state->src_w != new_state->src_w ||
1046 plane->state->src_h != new_state->src_h ||
1047 plane->state->crtc_w != new_state->crtc_w ||
1048 plane->state->crtc_h != new_state->crtc_h ||
1049 plane->state->fb != new_state->fb ||
1050 plane->state->fb == NULL)
1051 return -EINVAL;
1061 if (new_state->visible != plane->state->visible)
1062 return -EINVAL;
1071 struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
1073 plane->state->src_x = new_state->src_x;
1074 plane->state->src_y = new_state->src_y;
1075 plane->state->crtc_x = new_state->crtc_x;
1076 plane->state->crtc_y = new_state->crtc_y;
1078 if (new_state->visible) {
1084 value = (WIN_A_ACT_REQ << p->index) << 8 | GENERAL_UPDATE;
1088 value = (WIN_A_ACT_REQ << p->index) | GENERAL_ACT_REQ;
1120 return ERR_PTR(-ENOMEM);
1127 * need to special-casing the cursor plane.
1129 plane->index = 6;
1130 plane->dc = dc;
1132 if (!dc->soc->has_nvdisplay) {
1146 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
1155 drm_plane_helper_add(&plane->base, &tegra_cursor_plane_helper_funcs);
1156 drm_plane_create_zpos_immutable_property(&plane->base, 255);
1158 return &plane->base;
1168 /* non-native formats */
1205 /* semi-planar formats */
1245 /* semi-planar formats */
1268 return ERR_PTR(-ENOMEM);
1270 plane->offset = 0xa00 + 0x200 * index;
1271 plane->index = index;
1272 plane->dc = dc;
1274 num_formats = dc->soc->num_overlay_formats;
1275 formats = dc->soc->overlay_formats;
1288 err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
1297 drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs);
1298 drm_plane_create_zpos_property(&plane->base, plane->index, 0, 255);
1300 err = drm_plane_create_rotation_property(&plane->base,
1307 dev_err(dc->dev, "failed to create rotation property: %d\n",
1310 return &plane->base;
1319 for (i = 0; i < dc->soc->num_wgrps; i++) {
1320 const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
1322 if (wgrp->dc == dc->pipe) {
1323 for (j = 0; j < wgrp->num_windows; j++) {
1324 unsigned int index = wgrp->windows[j];
1333 wgrp->index,
1363 if (dc->soc->supports_cursor)
1374 while (i--)
1375 planes[i]->funcs->destroy(planes[i]);
1377 primary->funcs->destroy(primary);
1394 if (crtc->state)
1395 tegra_crtc_atomic_destroy_state(crtc, crtc->state);
1398 __drm_atomic_helper_crtc_reset(crtc, &state->base);
1406 struct tegra_dc_state *state = to_dc_state(crtc->state);
1413 __drm_atomic_helper_crtc_duplicate_state(crtc, &copy->base);
1414 copy->clk = state->clk;
1415 copy->pclk = state->pclk;
1416 copy->div = state->div;
1417 copy->planes = state->planes;
1419 return &copy->base;
1648 struct drm_info_node *node = s->private;
1649 struct tegra_dc *dc = node->info_ent->data;
1653 drm_modeset_lock(&dc->base.mutex, NULL);
1655 if (!dc->base.state->active) {
1656 err = -EBUSY;
1663 seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
1668 drm_modeset_unlock(&dc->base.mutex);
1674 struct drm_info_node *node = s->private;
1675 struct tegra_dc *dc = node->info_ent->data;
1679 drm_modeset_lock(&dc->base.mutex, NULL);
1681 if (!dc->base.state->active) {
1682 err = -EBUSY;
1690 drm_crtc_wait_one_vblank(&dc->base);
1691 drm_crtc_wait_one_vblank(&dc->base);
1699 drm_modeset_unlock(&dc->base.mutex);
1705 struct drm_info_node *node = s->private;
1706 struct tegra_dc *dc = node->info_ent->data;
1708 seq_printf(s, "frames: %lu\n", dc->stats.frames);
1709 seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
1710 seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
1711 seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
1713 seq_printf(s, "frames total: %lu\n", dc->stats.frames_total);
1714 seq_printf(s, "vblank total: %lu\n", dc->stats.vblank_total);
1715 seq_printf(s, "underflow total: %lu\n", dc->stats.underflow_total);
1716 seq_printf(s, "overflow total: %lu\n", dc->stats.overflow_total);
1730 struct drm_minor *minor = crtc->dev->primary;
1735 root = crtc->debugfs_entry;
1740 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1742 if (!dc->debugfs_files)
1743 return -ENOMEM;
1746 dc->debugfs_files[i].data = dc;
1748 drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1756 struct drm_minor *minor = crtc->dev->primary;
1761 root = crtc->debugfs_entry;
1766 drm_debugfs_remove_files(dc->debugfs_files, count, root, minor);
1767 kfree(dc->debugfs_files);
1768 dc->debugfs_files = NULL;
1776 if (dc->syncpt && !dc->soc->has_nvdisplay)
1777 return host1x_syncpt_read(dc->syncpt);
1780 return (u32)drm_crtc_vblank_count(&dc->base);
1826 if (!dc->soc->has_nvdisplay) {
1833 value = ((mode->vsync_end - mode->vsync_start) << 16) |
1834 ((mode->hsync_end - mode->hsync_start) << 0);
1837 value = ((mode->vtotal - mode->vsync_end) << 16) |
1838 ((mode->htotal - mode->hsync_end) << 0);
1841 value = ((mode->vsync_start - mode->vdisplay) << 16) |
1842 ((mode->hsync_start - mode->hdisplay) << 0);
1845 value = (mode->vdisplay << 16) | mode->hdisplay;
1852 * tegra_dc_state_setup_clock - check clock settings and store them in atomic
1861 * 0 on success or a negative error-code on failure.
1870 if (!clk_has_parent(dc->clk, clk))
1871 return -EINVAL;
1873 state->clk = clk;
1874 state->pclk = pclk;
1875 state->div = div;
1887 if (!dc->has_opp_table)
1891 rate = DIV_ROUND_UP(clk_get_rate(dc->clk) * 2, state->div + 2);
1894 opp = dev_pm_opp_find_freq_ceil(dc->dev, &rate);
1901 if (opp == ERR_PTR(-ERANGE))
1902 opp = dev_pm_opp_find_freq_floor(dc->dev, &rate);
1905 dev_err(dc->dev, "failed to find OPP for %luHz: %pe\n",
1920 err = dev_pm_genpd_set_performance_state(dc->dev, pstate);
1922 dev_err(dc->dev, "failed to set power domain state to %lu: %d\n",
1931 err = clk_set_parent(dc->clk, state->clk);
1933 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
1943 if (state->pclk > 0) {
1944 err = clk_set_rate(state->clk, state->pclk);
1946 dev_err(dc->dev,
1948 state->pclk);
1950 err = clk_set_rate(dc->clk, state->pclk);
1952 dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
1953 dc->clk, state->pclk, err);
1956 DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
1957 state->div);
1958 DRM_DEBUG_KMS("pclk: %lu\n", state->pclk);
1995 dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
1996 return -ETIMEDOUT;
2013 if (dc->soc->has_nvdisplay)
2018 if (!crtc->state->active) {
2019 if (!old_crtc_state->active)
2030 icc_set_bw(tegra->icc_mem, 0, 0);
2031 icc_set_bw(tegra->icc_mem_vfilter, 0, 0);
2037 for_each_old_plane_in_state(old_crtc_state->state, plane,
2040 new_tegra_state = to_const_tegra_plane_state(plane->state);
2048 if (tegra->dc != dc)
2051 new_avg_bw = new_tegra_state->avg_memory_bandwidth;
2052 old_avg_bw = old_tegra_state->avg_memory_bandwidth;
2054 new_peak_bw = new_tegra_state->total_peak_memory_bandwidth;
2055 old_peak_bw = old_tegra_state->total_peak_memory_bandwidth;
2058 * See the comment related to !crtc->state->active above,
2063 old_crtc_state->active)
2066 window.src.h = drm_rect_height(&plane->state->src) >> 16;
2067 window.dst.h = drm_rect_height(&plane->state->dst);
2069 old_window.src.h = drm_rect_height(&old_plane_state->src) >> 16;
2070 old_window.dst.h = drm_rect_height(&old_plane_state->dst);
2087 icc_set_bw(tegra->icc_mem, new_avg_bw, new_peak_bw);
2090 icc_set_bw(tegra->icc_mem_vfilter, new_avg_bw, new_peak_bw);
2092 icc_set_bw(tegra->icc_mem_vfilter, 0, 0);
2115 * these bits has the side-effect of stopping the display controller.
2129 if (dc->rgb) {
2136 tegra_dc_stats_reset(&dc->stats);
2139 spin_lock_irq(&crtc->dev->event_lock);
2141 if (crtc->state->event) {
2142 drm_crtc_send_vblank_event(crtc, crtc->state->event);
2143 crtc->state->event = NULL;
2146 spin_unlock_irq(&crtc->dev->event_lock);
2148 err = host1x_client_suspend(&dc->client);
2150 dev_err(dc->dev, "failed to suspend: %d\n", err);
2152 if (dc->has_opp_table) {
2153 err = dev_pm_genpd_set_performance_state(dc->dev, 0);
2155 dev_err(dc->dev,
2163 struct drm_display_mode *mode = &crtc->state->adjusted_mode;
2164 struct tegra_dc_state *crtc_state = to_dc_state(crtc->state);
2172 err = host1x_client_resume(&dc->client);
2174 dev_err(dc->dev, "failed to resume: %d\n", err);
2179 if (dc->syncpt) {
2180 u32 syncpt = host1x_syncpt_id(dc->syncpt), enable;
2182 if (dc->soc->has_nvdisplay)
2194 if (dc->soc->has_nvdisplay) {
2241 if (dc->soc->supports_background_color)
2247 if (!dc->soc->has_nvdisplay) {
2248 value = SHIFT_CLK_DIVIDER(crtc_state->div) | PIXEL_CLK_DIVIDER_PCD1;
2256 if (dc->soc->supports_interlacing) {
2267 if (!dc->soc->has_nvdisplay) {
2275 if (dc->soc->has_nvdisplay) {
2280 if (dc->rgb) {
2298 if (crtc->state->event) {
2299 spin_lock_irqsave(&crtc->dev->event_lock, flags);
2302 drm_crtc_send_vblank_event(crtc, crtc->state->event);
2304 drm_crtc_arm_vblank_event(crtc, crtc->state->event);
2306 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
2308 crtc->state->event = NULL;
2321 value = dc_state->planes << 8 | GENERAL_UPDATE;
2325 value = dc_state->planes | GENERAL_ACT_REQ;
2332 const struct tegra_dc_soc_info *soc = to_tegra_dc(state->crtc)->soc;
2333 const struct drm_format_info *fmt = state->fb->format;
2334 unsigned int src_w = drm_rect_width(&state->src) >> 16;
2335 unsigned int dst_w = drm_rect_width(&state->dst);
2337 if (state->plane->type != DRM_PLANE_TYPE_CURSOR)
2340 if (soc->supports_cursor)
2343 if (src_w != dst_w || fmt->num_planes != 1 || src_w * fmt->cpp[0] > 256)
2359 if (!plane_state->visible || !plane_state->fb)
2363 * Data-prefetch FIFO will easily help to overcome temporal memory
2370 rect = plane_state->dst;
2372 tegra = to_tegra_plane(other_state->plane);
2374 if (!other_state->visible || !other_state->fb)
2385 if (drm_rect_intersect(&rect, &other_state->dst))
2386 overlap_mask |= BIT(tegra->index);
2406 * The nv-display uses shared planes. The algorithm below assumes
2407 * maximum 3 planes per-CRTC, this assumption isn't applicable to
2408 * the nv-display. Note that T124 support has additional windows,
2411 if (dc->soc->has_nvdisplay)
2431 if (WARN_ON_ONCE(tegra->index >= TEGRA_DC_LEGACY_PLANES_NUM))
2432 return -EINVAL;
2434 plane_peak_bw[tegra->index] = tegra_state->peak_memory_bandwidth;
2436 overlap_mask[tegra->index] = mask;
2446 * fetches from the planes simultaneously during of scan-out process.
2450 * A-and-B or A-and-C planes overlap.
2461 * Note that plane's atomic check doesn't touch the
2469 for_each_set_bit(i, &overlap_mask[tegra->index], 3) {
2470 if (i == tegra->index)
2479 new_peak_bw = plane_peak_bw[tegra->index] + overlap_bw;
2480 old_peak_bw = tegra_state->total_peak_memory_bandwidth;
2497 new_tegra_state->total_peak_memory_bandwidth = new_peak_bw;
2545 dev_dbg(dc->dev, "%s(): frame end\n", __func__);
2547 dc->stats.frames_total++;
2548 dc->stats.frames++;
2553 dev_dbg(dc->dev, "%s(): vertical blank\n", __func__);
2555 drm_crtc_handle_vblank(&dc->base);
2556 dc->stats.vblank_total++;
2557 dc->stats.vblank++;
2562 dev_dbg(dc->dev, "%s(): underflow\n", __func__);
2564 dc->stats.underflow_total++;
2565 dc->stats.underflow++;
2570 dev_dbg(dc->dev, "%s(): overflow\n", __func__);
2572 dc->stats.overflow_total++;
2573 dc->stats.overflow++;
2577 dev_dbg_ratelimited(dc->dev, "%s(): head underflow\n", __func__);
2578 dc->stats.underflow_total++;
2579 dc->stats.underflow++;
2589 if (!dc->soc->wgrps)
2592 for (i = 0; i < dc->soc->num_wgrps; i++) {
2593 const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i];
2595 if (wgrp->dc == dc->pipe && wgrp->num_windows > 0)
2604 struct drm_device *drm = dev_get_drvdata(client->host);
2605 struct tegra_drm *tegra = drm->dev_private;
2607 tegra->num_crtcs++;
2614 struct drm_device *drm = dev_get_drvdata(client->host);
2617 struct tegra_drm *tegra = drm->dev_private;
2626 host1x_syncpt_release_vblank_reservation(client, 26 + dc->pipe);
2642 if (dc->soc->has_nvdisplay)
2643 client->parent = &tegra->hub->client;
2645 dc->syncpt = host1x_syncpt_request(client, flags);
2646 if (!dc->syncpt)
2647 dev_warn(dc->dev, "failed to allocate syncpoint\n");
2650 if (err < 0 && err != -ENODEV) {
2651 dev_err(client->dev, "failed to attach to domain: %d\n", err);
2655 if (dc->soc->wgrps)
2665 if (dc->soc->supports_cursor) {
2672 /* dedicate one overlay to mouse cursor */
2680 err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
2685 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
2691 if (dc->soc->pitch_align > tegra->pitch_align)
2692 tegra->pitch_align = dc->soc->pitch_align;
2695 if (dc->soc->has_nvdisplay)
2696 drm->mode_config.max_width = drm->mode_config.max_height = 16384;
2698 drm->mode_config.max_width = drm->mode_config.max_height = 4096;
2701 if (err < 0 && err != -ENODEV) {
2702 dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
2706 err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
2707 dev_name(dc->dev), dc);
2709 dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq,
2718 client->dev->dma_parms = client->host->dma_parms;
2730 host1x_syncpt_put(dc->syncpt);
2744 client->dev->dma_parms = NULL;
2746 devm_free_irq(dc->dev, dc->irq, dc);
2750 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
2755 host1x_syncpt_put(dc->syncpt);
2762 struct drm_device *drm = dev_get_drvdata(client->host);
2763 struct tegra_drm *tegra = drm->dev_private;
2765 tegra->num_crtcs--;
2773 struct device *dev = client->dev;
2776 err = reset_control_assert(dc->rst);
2782 if (dc->soc->has_powergate)
2783 tegra_powergate_power_off(dc->powergate);
2785 clk_disable_unprepare(dc->clk);
2794 struct device *dev = client->dev;
2803 if (dc->soc->has_powergate) {
2804 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2805 dc->rst);
2811 err = clk_prepare_enable(dc->clk);
2817 err = reset_control_deassert(dc->rst);
2827 clk_disable_unprepare(dc->clk);
3061 .compatible = "nvidia,tegra194-dc",
3064 .compatible = "nvidia,tegra186-dc",
3067 .compatible = "nvidia,tegra210-dc",
3070 .compatible = "nvidia,tegra124-dc",
3073 .compatible = "nvidia,tegra114-dc",
3076 .compatible = "nvidia,tegra30-dc",
3079 .compatible = "nvidia,tegra20-dc",
3093 err = of_property_read_u32(dc->dev->of_node, "nvidia,head", &value);
3095 dev_err(dc->dev, "missing \"nvidia,head\" property\n");
3110 if (np == dc->dev->of_node) {
3119 dc->pipe = value;
3129 return dc->pipe == pipe;
3139 if (dc->soc->coupled_pm && dc->pipe == 1) {
3143 companion = driver_find_device(dc->dev->driver, NULL, (const void *)0,
3146 return -EPROBE_DEFER;
3149 dc->client.parent = &parent->client;
3151 dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion));
3163 err = devm_tegra_core_dev_init_opp_table(dc->dev, &opp_params);
3164 if (err && err != -ENODEV)
3168 dc->has_opp_table = false;
3170 dc->has_opp_table = true;
3177 u64 dma_mask = dma_get_mask(pdev->dev.parent);
3181 err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
3183 dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
3187 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
3189 return -ENOMEM;
3191 dc->soc = of_device_get_match_data(&pdev->dev);
3193 INIT_LIST_HEAD(&dc->list);
3194 dc->dev = &pdev->dev;
3204 dc->clk = devm_clk_get(&pdev->dev, NULL);
3205 if (IS_ERR(dc->clk)) {
3206 dev_err(&pdev->dev, "failed to get clock\n");
3207 return PTR_ERR(dc->clk);
3210 dc->rst = devm_reset_control_get(&pdev->dev, "dc");
3211 if (IS_ERR(dc->rst)) {
3212 dev_err(&pdev->dev, "failed to get reset\n");
3213 return PTR_ERR(dc->rst);
3217 err = clk_prepare_enable(dc->clk);
3223 err = reset_control_assert(dc->rst);
3225 clk_disable_unprepare(dc->clk);
3231 clk_disable_unprepare(dc->clk);
3233 if (dc->soc->has_powergate) {
3234 if (dc->pipe == 0)
3235 dc->powergate = TEGRA_POWERGATE_DIS;
3237 dc->powergate = TEGRA_POWERGATE_DISB;
3239 tegra_powergate_power_off(dc->powergate);
3246 dc->regs = devm_platform_ioremap_resource(pdev, 0);
3247 if (IS_ERR(dc->regs))
3248 return PTR_ERR(dc->regs);
3250 dc->irq = platform_get_irq(pdev, 0);
3251 if (dc->irq < 0)
3252 return -ENXIO;
3255 if (err < 0 && err != -ENODEV)
3256 return dev_err_probe(&pdev->dev, err,
3260 pm_runtime_enable(&pdev->dev);
3262 INIT_LIST_HEAD(&dc->client.list);
3263 dc->client.ops = &dc_client_ops;
3264 dc->client.dev = &pdev->dev;
3266 err = host1x_client_register(&dc->client);
3268 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
3276 pm_runtime_disable(&pdev->dev);
3286 host1x_client_unregister(&dc->client);
3290 pm_runtime_disable(&pdev->dev);
3295 .name = "tegra-dc",