Lines Matching full:dc
33 #include "dc.h"
51 static u32 tegra_dc_readl_active(struct tegra_dc *dc, unsigned long offset)
55 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
56 value = tegra_dc_readl(dc, offset);
57 tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS);
80 dev_WARN(plane->dc->dev, "invalid offset: %x\n", 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));
97 bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)
99 struct device_node *np = dc->dev->of_node;
122 void tegra_dc_commit(struct tegra_dc *dc)
124 tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
125 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
318 struct tegra_dc *dc = plane->dc;
323 if (plane->index == 0 && dc->soc->has_win_a_without_filters)
333 struct tegra_dc *dc = plane->dc;
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;
428 if (dc->soc->supports_block_linear) {
534 if (dc->soc->has_legacy_blending)
630 struct tegra_dc *dc = to_tegra_dc(new_plane_state->crtc);
654 if (dc->soc->has_legacy_blending) {
665 !dc->soc->supports_block_linear) {
805 struct tegra_dc *dc)
822 plane->dc = dc;
824 num_formats = dc->soc->num_primary_formats;
825 formats = dc->soc->primary_formats;
826 modifiers = dc->soc->modifiers;
852 dev_err(dc->dev, "failed to create rotation property: %d\n",
908 struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
911 u64 dma_mask = *dc->dev->dma_mask;
924 if (!dc->soc->has_nvdisplay)
951 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
955 tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
959 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
961 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
963 value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
967 if (dc->soc->has_nvdisplay)
975 tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
978 if (dc->soc->has_nvdisplay) {
987 tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR);
991 tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR);
999 tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
1015 struct tegra_dc *dc;
1022 dc = to_tegra_dc(old_state->crtc);
1024 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
1026 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
1071 struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
1085 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
1086 (void)tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
1089 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
1090 (void)tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
1110 struct tegra_dc *dc)
1130 plane->dc = dc;
1132 if (!dc->soc->has_nvdisplay) {
1255 struct tegra_dc *dc,
1272 plane->dc = dc;
1274 num_formats = dc->soc->num_overlay_formats;
1275 formats = dc->soc->overlay_formats;
1307 dev_err(dc->dev, "failed to create rotation property: %d\n",
1314 struct tegra_dc *dc)
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) {
1332 plane = tegra_shared_plane_create(drm, dc,
1352 struct tegra_dc *dc)
1359 primary = tegra_primary_plane_create(drm, dc);
1363 if (dc->soc->supports_cursor)
1369 planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i,
1649 struct tegra_dc *dc = node->info_ent->data;
1653 drm_modeset_lock(&dc->base.mutex, NULL);
1655 if (!dc->base.state->active) {
1664 offset, tegra_dc_readl(dc, offset));
1668 drm_modeset_unlock(&dc->base.mutex);
1675 struct tegra_dc *dc = node->info_ent->data;
1679 drm_modeset_lock(&dc->base.mutex, NULL);
1681 if (!dc->base.state->active) {
1687 tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
1688 tegra_dc_commit(dc);
1690 drm_crtc_wait_one_vblank(&dc->base);
1691 drm_crtc_wait_one_vblank(&dc->base);
1693 value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
1696 tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
1699 drm_modeset_unlock(&dc->base.mutex);
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);
1732 struct tegra_dc *dc = to_tegra_dc(crtc);
1740 dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
1742 if (!dc->debugfs_files)
1746 dc->debugfs_files[i].data = dc;
1748 drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
1757 struct tegra_dc *dc = to_tegra_dc(crtc);
1766 drm_debugfs_remove_files(dc->debugfs_files, count, root, minor);
1767 kfree(dc->debugfs_files);
1768 dc->debugfs_files = NULL;
1773 struct tegra_dc *dc = to_tegra_dc(crtc);
1776 if (dc->syncpt && !dc->soc->has_nvdisplay)
1777 return host1x_syncpt_read(dc->syncpt);
1780 return (u32)drm_crtc_vblank_count(&dc->base);
1785 struct tegra_dc *dc = to_tegra_dc(crtc);
1788 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1790 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1797 struct tegra_dc *dc = to_tegra_dc(crtc);
1800 value = tegra_dc_readl(dc, DC_CMD_INT_MASK);
1802 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1819 static int tegra_dc_set_timings(struct tegra_dc *dc,
1826 if (!dc->soc->has_nvdisplay) {
1827 tegra_dc_writel(dc, 0x0, DC_DISP_DISP_TIMING_OPTIONS);
1830 tegra_dc_writel(dc, value, DC_DISP_REF_TO_SYNC);
1835 tegra_dc_writel(dc, value, DC_DISP_SYNC_WIDTH);
1839 tegra_dc_writel(dc, value, DC_DISP_BACK_PORCH);
1843 tegra_dc_writel(dc, value, DC_DISP_FRONT_PORCH);
1846 tegra_dc_writel(dc, value, DC_DISP_ACTIVE);
1854 * @dc: display controller
1863 int tegra_dc_state_setup_clock(struct tegra_dc *dc,
1870 if (!clk_has_parent(dc->clk, clk))
1880 static void tegra_dc_update_voltage_state(struct tegra_dc *dc,
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);
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",
1926 static void tegra_dc_set_clock_rate(struct tegra_dc *dc,
1931 err = clk_set_parent(dc->clk, state->clk);
1933 dev_err(dc->dev, "failed to set parent clock: %d\n", err);
1946 dev_err(dc->dev,
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),
1960 tegra_dc_update_voltage_state(dc, state);
1963 static void tegra_dc_stop(struct tegra_dc *dc)
1968 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
1970 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
1972 tegra_dc_commit(dc);
1975 static bool tegra_dc_idle(struct tegra_dc *dc)
1979 value = tegra_dc_readl_active(dc, DC_CMD_DISPLAY_COMMAND);
1984 static int tegra_dc_wait_idle(struct tegra_dc *dc, unsigned long timeout)
1989 if (tegra_dc_idle(dc))
1995 dev_dbg(dc->dev, "timeout waiting for DC to become idle\n");
2009 struct tegra_dc *dc = to_tegra_dc(crtc);
2013 if (dc->soc->has_nvdisplay)
2048 if (tegra->dc != dc)
2074 * freq should go high before the DC changes are committed
2099 struct tegra_dc *dc = to_tegra_dc(crtc);
2103 if (!tegra_dc_idle(dc)) {
2104 tegra_dc_stop(dc);
2110 tegra_dc_wait_idle(dc, 100);
2129 if (dc->rgb) {
2130 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
2133 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
2136 tegra_dc_stats_reset(&dc->stats);
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,
2165 struct tegra_dc *dc = to_tegra_dc(crtc);
2170 tegra_dc_set_clock_rate(dc, 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)
2188 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
2191 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
2194 if (dc->soc->has_nvdisplay) {
2197 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
2204 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
2208 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
2211 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
2213 tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS);
2217 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
2221 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
2226 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
2230 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
2234 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
2238 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
2241 if (dc->soc->supports_background_color)
2242 tegra_dc_writel(dc, 0, DC_DISP_BLEND_BACKGROUND_COLOR);
2244 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
2247 if (!dc->soc->has_nvdisplay) {
2249 tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
2253 tegra_dc_set_timings(dc, mode);
2256 if (dc->soc->supports_interlacing) {
2257 value = tegra_dc_readl(dc, DC_DISP_INTERLACE_CONTROL);
2259 tegra_dc_writel(dc, value, DC_DISP_INTERLACE_CONTROL);
2262 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_COMMAND);
2265 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_COMMAND);
2267 if (!dc->soc->has_nvdisplay) {
2268 value = tegra_dc_readl(dc, DC_CMD_DISPLAY_POWER_CONTROL);
2271 tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
2275 if (dc->soc->has_nvdisplay) {
2277 tegra_dc_writel(dc, value, DC_COM_RG_UNDERFLOW);
2280 if (dc->rgb) {
2283 tegra_dc_writel(dc, value, DC_DISP_SHIFT_CLOCK_OPTIONS);
2286 tegra_dc_commit(dc);
2318 struct tegra_dc *dc = to_tegra_dc(crtc);
2322 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
2323 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
2326 tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL);
2327 value = tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
2400 struct tegra_dc *dc = to_tegra_dc(crtc);
2411 if (dc->soc->has_nvdisplay)
2445 * overlapping planes, where "simultaneously" means areas where DC
2537 struct tegra_dc *dc = data;
2540 status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
2541 tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
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++;
2585 static bool tegra_dc_has_window_groups(struct tegra_dc *dc)
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)
2616 struct tegra_dc *dc = host1x_client_to_dc(client);
2623 * DC has been reset by now, so VBLANK syncpoint can be released
2626 host1x_syncpt_release_vblank_reservation(client, 26 + dc->pipe);
2633 if (!tegra_dc_has_window_groups(dc))
2642 if (dc->soc->has_nvdisplay)
2645 dc->syncpt = host1x_syncpt_request(client, flags);
2646 if (!dc->syncpt)
2647 dev_warn(dc->dev, "failed to allocate syncpoint\n");
2655 if (dc->soc->wgrps)
2656 primary = tegra_dc_add_shared_planes(drm, dc);
2658 primary = tegra_dc_add_planes(drm, dc);
2665 if (dc->soc->supports_cursor) {
2666 cursor = tegra_dc_cursor_plane_create(drm, dc);
2673 cursor = tegra_dc_overlay_plane_create(drm, dc, 2, true);
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)
2700 err = tegra_dc_rgb_init(drm, dc);
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,
2730 host1x_syncpt_put(dc->syncpt);
2737 struct tegra_dc *dc = host1x_client_to_dc(client);
2740 if (!tegra_dc_has_window_groups(dc))
2746 devm_free_irq(dc->dev, dc->irq, dc);
2748 err = tegra_dc_rgb_exit(dc);
2750 dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);
2755 host1x_syncpt_put(dc->syncpt);
2772 struct tegra_dc *dc = host1x_client_to_dc(client);
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);
2793 struct tegra_dc *dc = host1x_client_to_dc(client);
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);
2960 .dc = 0,
2965 .dc = 1,
2970 .dc = 1,
2975 .dc = 2,
2980 .dc = 2,
2985 .dc = 2,
3011 .dc = 0,
3016 .dc = 1,
3021 .dc = 1,
3026 .dc = 2,
3031 .dc = 2,
3036 .dc = 2,
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",
3087 static int tegra_dc_parse_dt(struct tegra_dc *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;
3126 struct tegra_dc *dc = dev_get_drvdata(dev);
3129 return dc->pipe == pipe;
3132 static int tegra_dc_couple(struct tegra_dc *dc)
3139 if (dc->soc->coupled_pm && dc->pipe == 1) {
3143 companion = driver_find_device(dc->dev->driver, NULL, (const void *)0,
3149 dc->client.parent = &parent->client;
3151 dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion));
3158 static int tegra_dc_init_opp_table(struct tegra_dc *dc)
3163 err = devm_tegra_core_dev_init_opp_table(dc->dev, &opp_params);
3168 dc->has_opp_table = false;
3170 dc->has_opp_table = true;
3178 struct tegra_dc *dc;
3187 dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
3188 if (!dc)
3191 dc->soc = of_device_get_match_data(&pdev->dev);
3193 INIT_LIST_HEAD(&dc->list);
3194 dc->dev = &pdev->dev;
3196 err = tegra_dc_parse_dt(dc);
3200 err = tegra_dc_couple(dc);
3204 dc->clk = devm_clk_get(&pdev->dev, NULL);
3205 if (IS_ERR(dc->clk)) {
3207 return PTR_ERR(dc->clk);
3210 dc->rst = devm_reset_control_get(&pdev->dev, "dc");
3211 if (IS_ERR(dc->rst)) {
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);
3242 err = tegra_dc_init_opp_table(dc);
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)
3254 err = tegra_dc_rgb_probe(dc);
3259 platform_set_drvdata(pdev, dc);
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);
3277 tegra_dc_rgb_remove(dc);
3284 struct tegra_dc *dc = platform_get_drvdata(pdev);
3286 host1x_client_unregister(&dc->client);
3288 tegra_dc_rgb_remove(dc);
3295 .name = "tegra-dc",